Spring 一共有几种注入方式?
- 标签:后端、Spring
🏛 业务架构师
Spring 的注入方式按载体分三种:构造器注入、Setter 注入、字段注入(此外还有接口回调时代的方法注入,现已少见)。按装配来源又有 @Autowired/@Inject 按类型、@Qualifier/@Resource 按名称、集合注入(注入 List<Strategy> 拿到所有实现)等。
我的团队规范是构造器注入为默认,理由都指向业务质量:
- 依赖显式可见:构造参数就是类的"依赖清单",超过 5 个就该拆类——它是天然的职责膨胀报警器;
- 对象不可能半成品:字段可
final,注入不全就创建失败,问题在编码期暴露而不是运行期偶发 NPE; - 利于测试:单测直接
new对象传 Mock,不依赖容器和反射。
Setter 注入保留给真正的可选依赖(有合理默认值的场景)。字段注入我基本禁用:写起来快,但依赖被藏起来、无法脱离容器构造、掩盖循环依赖。
再补一个业务扩展性技巧:注入 List<DiscountStrategy> 或 Map<String, Handler>,Spring 会自动收集所有实现,新增策略类零配置接入——营销规则、审批流、多租户定制这类"业务规则会持续生长"的领域,这个模式回报极高。
一句话:注入方式的选择体现工程纪律,构造器注入是性价比最高的默认项。
🏗 系统架构师
按手段分三种,我的选型纪律:
- 构造器注入(默认):不可变、依赖显式、fail-fast;4.3 起单构造器免注解,配合 Lombok
@RequiredArgsConstructor或 record 一行搞定; - setter 注入:仅用于真正可选、可变的依赖(配置型参数);
- 字段注入:仅测试代码。隐藏依赖、破坏封装、脱离容器无法实例化,生产代码禁止。
另一个维度是装配来源:注解(@Autowired、@Resource、构造器)、XML、@Bean 方法、自动装配(byType/byName)。XML 只在存量系统,新系统一律注解加 Java Config。
架构治理点:构造器参数超过 5 个我视为「上帝类」信号,当场拆分。注入方式的选择本质是依赖治理——让依赖图显式、可静态分析,IDE 与 ArchUnit 才能做架构约束检查,团队规模越大这条越重要。
💻 全栈开发专家
四种:构造器、setter、字段、普通方法(少见)。团队规范默认构造器注入:
java
// 构造器注入(配 Lombok 零样板)
@Service
@RequiredArgsConstructor
public class OrderService {
private final StockClient stockClient;
}
// setter 注入:可选依赖、循环依赖兜底
@Autowired
public void setStockClient(StockClient stockClient) { ... }
// 字段注入(不推荐)
@Autowired
private StockClient stockClient;选择逻辑:
- 构造器为默认:可 final、依赖透明、单测直接 new、循环依赖编译期暴露
- setter/字段注入留给可选依赖(
@Autowired(required=false))或历史代码 - 多构造器时用
@Autowired标记主构造器
注解维度还有 @Resource(JSR-250,先按名字后按类型)和 @Inject(JSR-330),差异主要在匹配顺序。我处理过最多的相关事故是"字段注入 + 循环依赖"在 Boot 2.6 升级时集中爆雷,团队禁掉字段注入后这类问题绝迹——这也是 IDEA 给字段注入黄色警告的原因。