关键在于理清“谁在什么时候、以什么方式把什么对象给了谁”:Bean是容器创建管理的对象,依赖是其运行所需其他Bean;构造器注入适用于强制依赖,Setter用于可选依赖,字段注入应避免;注入发生在实例化后、初始化前,构造器中调用注入对象会空指针;循环依赖暴露设计问题,应重构而非绕过。

掌握 Spring Boot 依赖注入,关键不是背注解,而是理清“谁在什么时候、以什么方式把什么对象给了谁”。下面从四个最常卡壳的环节切入,直击本质。
搞懂 Bean 和依赖的本质区别
Bean 是被 Spring 容器创建并管理的对象(比如加了 @Service 的类);依赖是某个 Bean 运行时需要的其他 Bean(比如 UserService 需要 UserDao)。别混淆“被管的对象”和“被用的对象”。一个类可以是 Bean,也可以是别人的依赖,还能同时依赖别人——三重身份很常见。
三种注入方式必须分清适用场景
- 构造器注入:适合强制依赖。对象一创建就必须有它,且不可变(建议配合 final 字段)。Spring 4.3+ 单构造函数可省略 @Autowired,自动装配。
- Setter 注入:适合可选依赖或后期动态替换(如策略切换),但线程安全性弱,一般少用。
- 字段注入:写起来最简单,但破坏封装、无法做单元测试、易引发 NPE,生产环境应避免。
理解注入发生的准确时机
注入发生在实例化之后、初始化之前。也就是说:
- 构造方法执行时,所有 @Autowired 字段仍是 null;
- 构造完才开始注入依赖;
- 所以千万别在构造器里调用注入对象的方法——会空指针。
循环依赖不是“不能解”,而是“不该存在”
Spring 默认禁止循环依赖(2.6+ 版本启动直接报错),因为它暴露的是设计问题。常见链路如 A→B→C→A,本质是职责划分不清。优先考虑重构:提取公共逻辑到新 Service,或引入事件机制解耦。若临时绕过,可用 @Lazy 延迟加载某一方,但这只是掩耳盗铃,不解决根本。


















