@Autowired 的实现原理
@Autowired
是 Spring 中最常用的依赖注入注解之一,它的底层实现涉及多个核心组件和机制。理解其源码实现有助于深入掌握 Spring 的 依赖注入(DI) 原理。
🧠 一、@Autowired 的作用
✅ 功能概述:
- 自动装配 Bean
- 支持字段注入、构造器注入、Setter 注入
- 支持按类型匹配(默认)、结合
@Qualifier
按名称匹配
✅ 示例使用方式:
@Component
class A {@Autowiredprivate B b;
}@Component
class B {}
🔄 二、@Autowired 的工作原理与流程
Spring 在创建 Bean 的过程中会解析 @Autowired
注解,并自动注入依赖对象。整个过程主要由以下组件协作完成:
类名 | 职责 |
---|---|
AutowiredAnnotationBeanPostProcessor | 处理 @Autowired 、@Value 等注解 |
DefaultListableBeanFactory.resolveDependency() | 解析依赖项(按类型查找匹配的 Bean) |
InjectionMetadata | 存储要注入的字段或方法信息 |
BeanWrapperImpl | 实际进行属性赋值 |
🔍 三、关键源码分析
📁 核心类路径:
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
org.springframework.beans.factory.annotation.InjectionMetadata
org.springframework.beans.factory.support.DefaultListableBeanFactory
1️⃣ AutowiredAnnotationBeanPostProcessor
:主处理器
这个类是 BeanPostProcessor
的一个实现,负责在 Bean 创建前后处理 @Autowired
注解。
关键方法:
public class AutowiredAnnotationBeanPostProcessor implements MergedBeanDefinitionPostProcessor {// 找出类中所有带有 @Autowired 的字段/方法@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);metadata.checkConfigMembers(beanDefinition);}// 在 Bean 初始化之前注入依赖@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {try {InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), bean);metadata.inject(bean, beanName, null); // 执行注入} catch (Throwable ex) {throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);}return bean;}
}
2️⃣ InjectionMetadata
:存储注入元数据
该类封装了需要注入的字段或方法信息。
private InjectionMetadata(Class<?> targetClass, Collection<InjectedElement> elements) {this.targetClass = targetClass;this.injectedElements = elements;
}public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {for (InjectedElement element : this.injectedElements) {element.inject(target, beanName, pvs); // 对每个字段执行注入}
}
3️⃣ AutowiredFieldElement
:字段注入逻辑
针对字段注入的情况,Spring 使用 AutowiredFieldElement
来处理。
private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {@Overrideprotected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {Field field = getField();Object value = resolveFieldValue(field, bean, beanName); // 解析值if (value != null) {ReflectionUtils.makeAccessible(field);field.set(bean, value); // 使用反射设置字段值}}private Object resolveFieldValue(Field field, Object bean, String beanName) {DependencyDescriptor descriptor = new DependencyDescriptor(field, true);return getBeanFactory().resolveDependency(descriptor, beanName); // 解析依赖}
}
4️⃣ DefaultListableBeanFactory.resolveDependency()
:解析依赖
这是 Spring 依赖注入的核心方法,用于根据类型查找并返回合适的 Bean。
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName) {// 获取目标类型Class<?> typeToMatch = descriptor.getDependencyType();// 查找所有匹配的 Bean 名称String[] candidateNames = getBeanNamesForType(typeToMatch);if (candidateNames.length == 1) {// 如果只有一个匹配项,直接返回return getBean(candidateNames[0]);} else if (candidateNames.length > 1) {// 如果有多个匹配项,尝试结合 @Qualifier 进行筛选Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length);for (String candidateName : candidateNames) {if (!isSelfReference(requestingBeanName, candidateName, descriptor)) {candidates.put(candidateName, getBean(candidateName));}}// 使用 Qualifier 或 Primary 来决定最终选择哪个 Beanreturn determinePrimaryCandidate(candidates, descriptor);} else {// 没有找到匹配的 Beanreturn null;}
}
⚙️ 四、@Autowired 注入的关键机制
1. 依赖查找机制
- Spring 通过
getBeanNamesForType()
方法查找容器中所有符合指定类型的 Bean。 - 支持泛型注入(如
List<A>
、Map<String, A>
)
2. 多实例匹配问题
当有多个相同类型的 Bean 时,可以通过以下方式解决冲突:
@Primary
:标记首选 Bean@Qualifier("beanName")
:指定具体 Bean 名称- 结合自定义限定符注解(如
@MyQualifier
)
3. 注入时机
- 字段注入发生在
postProcessBeforeInitialization()
阶段 - 构造器注入则在 Bean 实例化阶段就完成(通过
autowireConstructor()
)
🧱 五、支持的注入方式对比
注入方式 | 是否支持 | 说明 |
---|---|---|
字段注入 | ✅ | 最常用,但不推荐用于生产代码(破坏封装) |
Setter 注入 | ✅ | 推荐用于可选依赖 |
构造器注入 | ✅ | 推荐用于强制依赖,不可变对象更安全 |
方法注入(任意方法) | ✅ | 如 @Autowired public void init(A a) |
❓六、常见问题 & 面试题(结合源码)
Q1: @Autowired
是如何实现的?
Spring 使用
AutowiredAnnotationBeanPostProcessor
在 Bean 初始化前扫描类中的@Autowired
注解,然后通过反射注入对应的依赖对象。
Q2: @Autowired
和 @Resource
有什么区别?
特性 | @Autowired | @Resource |
---|---|---|
来源 | Spring | JDK(JSR-250) |
默认行为 | 按类型注入 | 按名称注入 |
是否支持 required=false | ✅ | ❌ |
是否支持 JSR-330 (@Inject ) | ❌ | ✅ |
Q3: 多个同类型 Bean 如何注入?
Spring 会抛出异常(NoUniqueBeanDefinitionException),可通过
@Primary
或@Qualifier
明确指定注入哪一个 Bean。
Q4: @Autowired
可以用在哪些地方?
支持字段、构造器、Setter、任意方法上,甚至可以用于
List
、Map
、数组等集合类型。
✅ 总结
特性 | Spring @Autowired 实现 |
---|---|
注解处理器 | AutowiredAnnotationBeanPostProcessor |
注入元数据 | InjectionMetadata |
字段注入 | AutowiredFieldElement |
构造器注入 | autowireConstructor() |
依赖解析 | resolveDependency() |
多 Bean 冲突 | 支持 @Primary , @Qualifier 解决 |
注入时机 | postProcessBeforeInitialization() 阶段 |