Spring 依赖注入(DI)
依赖注入(DI)
在 Spring 中,依赖注入(Dependency Injection, DI)是核心特性。它通过 IoC 容器管理 Bean 的依赖关系,从而避免手动 new 对象,提升了代码的解耦性和可维护性。
2.1 @Autowired 自动装配
@Autowired 是 Spring 提供的注解,用于让容器自动完成依赖注入。
要实现自动注入,不一定非要写 @Autowired,因为 Spring 在某些场景下会自动完成:
- @Bean 方法的参数会自动注入
- 构造函数的参数会自动注入
特性
构造函数
- 如果 Bean 只有一个有参构造函数,即使省略 @Autowired,Spring 也会自动注入参数
- 如果有多个有参构造函数,且没有无参构造函数,会报错。此时需要用 @Autowired 明确指定
- 构造函数上的 required 属性会失效
参数
- 如果想设置某个构造函数参数不是必须的,可以单独标记
- 在单元测试中也可以直接对方法参数使用
方法
- Spring 会自动调用被 @Autowired 标记的方法,并完成参数注入
装配规则
- Spring 会先根据 类型 去容器中查找 (byType)
- 如果有多个同类型的 Bean,再根据 名字 查找 (byName)
- 如果还是找不到,可以通过以下方式解决:
- 使用 @Primary 指定某个 Bean 为主要候选
- 使用 @Qualifier(“beanName”) 指定 Bean 的名字
容错处理
- 如果容器中一个都没找到,会报错
- 可以通过 @Autowired(required = false) 避免报错
示例代码:
1 | @Service |
2.2 @Inject 和 @Resource
除了 @Autowired,我们还可以使用 JDK 提供的注解。
@Inject
- JSR-330 标准
- 和 @Autowired 类似,但不能设置 required = false
示例:
1 | import javax.inject.Inject; |
@Resource
- JSR-250 标准
- 先根据名字查找,再根据类型查找
示例:
1 | import javax.annotation.Resource; |
IDEA 为什么不建议在字段上使用 @Autowired
- 字段通常是 private,通过 @Autowired 注入会破坏封装性
- 依赖注入应通过构造函数或方法完成,便于单元测试和维护
推荐的做法:
- 使用构造函数注入(最推荐)
- 使用 @Resource 指定 Bean
- 在字段上用 @Autowired 也不是错误,但不够优雅
2.3 @Value
@Value 用于给字段注入值,可以是常量、配置文件中的属性,或者表达式。
常见用法
直接赋值:
1 | @Value("ceshi") |
引用配置文件属性:
1 | # application.properties |
外部配置文件(非 Spring Boot):
需要通过 @PropertySource 指定:
1 | @Component |
默认值:
1 | @Value("${user.address:默认地址}") |
SpEL 表达式:
1 | @Value("#{1+2}") |
总结
依赖注入的推荐做法:
- 优先使用构造函数注入,保证依赖的不可变性和可测试性
- 在 Bean 选择时,合理使用 @Primary 或 @Qualifier
- 配置值注入用 @Value,支持默认值和 SpEL 表达式
- @Autowired 和 @Inject/@Resource 都可以用,根据习惯或团队规范选择
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Emqo的个人博客!
评论