当前位置: 首页 > news >正文

@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
来源SpringJDK(JSR-250)
默认行为按类型注入按名称注入
是否支持 required=false
是否支持 JSR-330 (@Inject)

Q3: 多个同类型 Bean 如何注入?

Spring 会抛出异常(NoUniqueBeanDefinitionException),可通过 @Primary@Qualifier 明确指定注入哪一个 Bean。

Q4: @Autowired 可以用在哪些地方?

支持字段、构造器、Setter、任意方法上,甚至可以用于 ListMap、数组等集合类型。


✅ 总结

特性Spring @Autowired 实现
注解处理器AutowiredAnnotationBeanPostProcessor
注入元数据InjectionMetadata
字段注入AutowiredFieldElement
构造器注入autowireConstructor()
依赖解析resolveDependency()
多 Bean 冲突支持 @Primary, @Qualifier 解决
注入时机postProcessBeforeInitialization() 阶段

相关文章:

  • 基于 SpringBoot + Vue 的校园管理系统设计与实现
  • .net在DB First模式使用pgsql
  • Java Web 开发:过滤器 (Filter) vs 拦截器 (Interceptor) - 深度剖析与选择指南
  • C++ std::sort 函数
  • JS进阶DAY2 构造函数数据常用函数
  • 能效提升超 61%!Fortinet 发布《2024 年可持续发展报告》
  • 精益数据分析(47/126):深挖UGC商业模式的关键要点与指标
  • 5月7号.
  • k8s | Kubernetes 服务暴露:NodePort、Ingress 与 YAML 配置详解
  • 企业级AI革命!私有化部署开源大模型:数据安全+自主可控,打造专属智能引擎
  • 线性代数之矩阵运算:驱动深度学习模型进化的数学引擎
  • Ubuntu安装pgsql
  • 配电站室智能巡检:机器人 VS 固定摄像头,谁更胜一筹?
  • Spark-Core(RDD行动算子)
  • 【PhysUnits】2.2 Scalar<T> 标量元组结构体(scalar/mod.rs)
  • idea左侧项目资源管理器不见了处理
  • bpftrace 中使用 bpf_trace_printk
  • 【MCP】客户端配置(ollama安装、qwen2.5:0.5b模型安装、cherry-studio安装配置)
  • KL散度(Kullback-Leibler Divergence):概率分布差异的量化利器
  • MCP认证全解析:从零到微软认证专家
  • 庆祝上海总工会成立100周年暨市模范集体劳动模范和先进工作者表彰大会举行,陈吉宁寄予这些期待
  • 2025年度上海市住房城乡建设管理委工程系列中级职称评审工作启动
  • 欧盟决意与俄罗斯能源彻底决裂之际,美国谋划新生意:进口俄气对欧转售
  • 中方是否认同俄方关于新纳粹主义观点?外交部:联大曾多次通过相关决议
  • 马克思主义理论研究教学名师系列访谈|董雅华:让学生感知马克思主义理论存在于社会生活中
  • 洛杉矶奥组委确认2028年奥运会和残奥会开闭幕式场地