Spring DI详解:注入方式与实现
1. DI(依赖注入)概述
DI(Dependency Injection,依赖注入)是Spring框架实现IoC(控制反转)的核心机制。DI通过将依赖关系"注入"到对象中,避免对象自行管理其依赖,从而降低耦合度,提高系统灵活性。
2. 依赖注入实现方式
2.1 属性注入
通过Autowired注解实现属性注入:
示例代码:
@Service
public class ComponentService {
public void doService() {
System.out.println("执行服务逻辑...");
}
}
@Controller
public class UserCtrl {
@Autowired
private ComponentService componentService;
public void doUserCtrl() {
componentService.doService();
System.out.println("执行控制器逻辑...");
}
}
2.2 构造方法注入
通过构造方法参数实现依赖注入:
示例代码:
@Controller
public class UserCtrl {
private ComponentService componentService;
private UserModel userModel;
public UserCtrl(ComponentService componentService) {
this.componentService = componentService;
}
public UserCtrl(ComponentService componentService, UserModel userModel) {
this.componentService = componentService;
this.userModel = userModel;
}
public void doUserCtrl() {
componentService.doService();
System.out.println("执行控制器逻辑...");
}
}
2.3 Setter注入
通过Setter方法和Autowired注解实现注入:
示例代码:
@Controller
public class UserCtrl {
private ComponentService componentService;
@Autowired
public void setComponentService(ComponentService componentService) {
this.componentService = componentService;
}
public void doUserCtrl() {
componentService.doService();
System.out.println("执行控制器逻辑...");
}
}
3. 自动注入问题与解决方案
当存在多个相同类型Bean时,Spring提供以下解决方案:
- 基于Bean名称注入:使用@Qualifier注解指定Bean名称
- 设置默认Bean:使用@Primary注解指定默认Bean
- 使用@Resource注解:根据Bean名称注入
示例代码:
@Configuration
public class AppConfig {
@Bean
public String getName() { return "张三"; }
@Bean
@Primary
public UserModel getUserModel() {
UserModel userModel = new UserModel();
userModel.setId(1);
userModel.setName(getName());
userModel.setAge(20);
return userModel;
}
}
4. 常见注解说明
| 注解 | 功能 |
|---|---|
| @Autowired | 根据类型或名称注入Bean,默认按类型注入 |
| @Qualifier | 指定Bean名称进行注入 |
| @Primary | 指定默认Bean,在类型冲突时使用 |
| @Resource | 根据Bean名称注入 |
5. 注入方式对比
| 注入方式 | 优点 | 缺点 |
|---|---|---|
| 属性注入 | 简洁方便 | 不支持Final属性 |
| 构造注入 | 强制初始化依赖,支持Final | 代码冗余度较高 |
| Setter注入 | 支持动态配置 | 不支持Final属性,存在被修改风险 |