Spring 自动装配原理
2026/9/7 11:04:09 网站建设 项目流程

目录

1、整体流程

2、查找 Bean 规则(@Autowired)

① 优先按类型查找 byType

情况 1:容器中该类型只有 1 个 Bean → 直接注入。

情况 2:同类型多个 Bean(多个实现类)

required 属性

3、三种注入位置区别

1)字段注入(不推荐)

2)setter 方法注入

3)构造器注入(Spring 官方推荐)

4、@Resource 和 @Autowired 对比(高频面试)

5、核心源码链路(精简)

6、循环依赖与自动装配

7、常见坑

面试简答版(背)


自动装配:Spring 根据类型,自动在容器中查找 Bean,完成依赖注入,对应@Autowired。 核心类:AutowiredAnnotationBeanPostProcessor,它是 Bean 后置处理器,在 Bean 实例化完成之后、初始化之前执行依赖注入

1、整体流程

  1. Spring 启动,扫描所有@Autowired/@Value注解,由AutowiredAnnotationBeanPostProcessor解析。
  2. Bean 实例化(构造器执行完成,对象已经 new 出来)。
  3. 执行后置处理器postProcessProperties解析当前类的字段、set 方法上的 @Autowired
  4. 根据依赖的类型BeanFactory查找匹配 Bean。
  5. 找到之后通过反射给字段 / 方法赋值,完成注入。
  6. 之后才执行@PostConstruct、InitializingBean 初始化逻辑。

⚠️ 关键点:实例化 ≠ 初始化

  • 实例化:new 对象
  • 自动装配(依赖注入)发生在实例化之后,初始化之前。

2、查找 Bean 规则(@Autowired)

① 优先按类型查找byType

java

@Autowired private UserService userService;

去容器找UserService类型的 Bean。

情况 1:容器中该类型只有 1 个 Bean → 直接注入。
情况 2:同类型多个 Bean(多个实现类)
  1. 按类型查到多个,再用变量名(字段名)作为 beanName二次匹配。
  2. 仍然匹配失败,抛出NoUniqueBeanDefinitionException
  3. 此时可以搭配@Qualifier("beanName")指定 bean 名称,限定查找。

java

@Autowired @Qualifier("userServiceImpl2") private UserService userService;

required 属性

@Autowired(required = false)

  • required=true(默认):找不到 Bean 直接抛异常。
  • required=false:找不到就置为 null,不报错。

3、三种注入位置区别

1)字段注入(不推荐)

java

@Autowired private UserService userService;
  • 通过反射直接给 private 字段赋值。
  • 缺点:循环依赖不易察觉、不利于单元测试、容易产生 NPE。

2)setter 方法注入

java

@Autowired public void setUserService(UserService userService){ this.userService = userService; }

解析 setXxx 方法参数类型,查找 Bean 调用方法赋值。

3)构造器注入(Spring 官方推荐)

Spring4.3 优化:类只有一个构造函数时,@Autowired 可以省略,自动构造器注入。

java

@Autowired public UserController(UserService userService){ this.userService = userService; }

注意:构造器注入发生在实例化阶段,对象还没 new 完成,和字段 /set 注入时机不一样。

4、@Resource 和 @Autowired 对比(高频面试)

特性@Autowired(Spring)@Resource (JSR‑250 Java 标准)
来源Spring 注解Java 官方
默认规则byType,类型优先,再匹配 namebyName名字优先,名字找不到退化成 byType
required支持required=false不支持
@Qualifier配合使用使用name="beanName"

java

@Resource(name="userServiceImpl1") private UserService userService;

5、核心源码链路(精简)

AutowiredAnnotationBeanPostProcessor

  1. postProcessProperties()→ 入口
  2. findAutowiringMetadata():收集类上所有 @Autowired 标记的字段、方法元数据InjectionMetadata
  3. inject():执行注入
    • 字段:Field反射 set
    • 方法:反射调用方法
  4. beanFactory.resolveDependency()核心方法,解析依赖,去容器查找 Bean
    • doResolveDependency()
      • findAutowireCandidates():根据 type 找到所有候选 Bean
      • 判断数量:单个直接返回;多个按字段名匹配 beanName;冲突抛异常。

6、循环依赖与自动装配

  1. 构造器注入会直接循环依赖报错:实例化阶段互相需要对方,对象创建不出来。
  2. 字段 /setter @Autowired 可以解决循环依赖:依靠 Spring 三级缓存。
    • A 先实例化,放入三级缓存;A 需要 B,开始创建 B;B 又需要 A,从缓存拿到半成品 A;B 完成;再注入 A,完成装配。

三级缓存只能解决:singleton 单例、setter / 字段注入,原型 prototype 不支持循环依赖。

7、常见坑

  1. @Autowired接口,多个实现类忘记@QualifierNoUniqueBeanDefinitionException
  2. @Autowired(required=false)没判断 null,运行 NPE。
  3. 构造器多个构造函数,不写@Autowired,Spring 不知道选哪个构造器,启动失败。
  4. this.xxx获取自动装配对象为 null:this 是 new 出来的普通对象,不是 Spring 容器 Bean,不会走后置处理器注入

面试简答版(背)

@Autowired自动装配由AutowiredAnnotationBeanPostProcessor后置处理器实现。在 Bean 实例化完成之后,解析字段、set 方法注解,优先按类型 byType从容器查找 Bean;如果找到多个同类型 Bean,再使用字段名作为 beanName 匹配;配合@Qualifier可以显式指定 Bean 名称。required控制找不到是否抛异常。

@Resource是 Java 标准注解,默认按名称 byName 查找,找不到才降级按类型。 构造器注入如果只有一个构造器,注解可以省略;构造器注入无法解决循环依赖,字段 setter 注入依靠三级缓存可以处理单例循环依赖。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询