Spring 提供多种方式实现依赖注入(DI),用于管理和使用各种 Bean
。依赖注入的目的是将对象的依赖关系交由 Spring 容器管理,提升代码的可维护性和解耦性。
1. Lombok + 构造函数注入(重点推荐)
1.1 背景
构造函数注入是最佳实践,但当类需要注入的依赖较多时,手写构造函数会显得繁琐冗长。Lombok 提供的 @RequiredArgsConstructor
注解可以解决这个问题。
1.2 实现方式
使用 @RequiredArgsConstructor:
-
@RequiredArgsConstructor
会自动为所有final
字段生成一个包含这些字段的构造函数。 -
Spring 会自动使用这个构造函数进行依赖注入。
@Component
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final EmailService emailService;
public void registerUser(User user) {
userRepository.save(user);
emailService.sendWelcomeEmail(user.getEmail());
}
}
1.3 优点
-
简洁性:减少构造函数的重复书写,代码更清晰。
-
安全性:所有依赖字段均为
final
,不可变。 -
维护性:依赖关系一目了然,符合最佳实践。
-
兼容性:无需额外配置,Lombok 生成的构造函数与 Spring 无缝集成。
1.4 缺点
-
引入 Lombok:需要在项目中使用 Lombok,虽然是开发效率的提升工具,但对项目有一定的侵入性。
2. 构造函数注入(Spring 推荐)
2.1 用法
通过构造函数将依赖注入到类中。
2.2 实现方式
将依赖声明为构造函数的参数,并使用 @Autowired
或让 Spring 自动发现。
通过构造函数将依赖注入到类中:
@Component
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
2.3 优点
-
明确依赖关系,符合单一职责原则。
-
依赖是不可变的(
final
)。 -
易于测试:可以在构造函数中传入 mock 对象。
2.4 缺点
- 如果依赖过多,构造函数会变得冗长。
3. 字段注入
3.1 用法
在类中直接通过注解将依赖的 Bean
注入到字段中。
3.2 实现方式
-
使用
@Autowired
注解(Spring 提供) -
使用
@Resource
注解(Java 标准)
直接在类的字段上使用注解注入依赖:
@Component
public class UserService {
@Autowired
private UserRepository userRepository;
@Resource
private EmailService emailService;
public void registerUser(User user) {
userRepository.save(user);
emailService.sendWelcomeEmail(user.getEmail());
}
}
3.3 优点
- 简单直接,不需要构造函数或
set
方法。
3.4 缺点
-
不推荐:依赖关系不明确,不符合单一职责原则。
-
测试时不易注入 mock 对象。
4. Set 方法注入
4.1 用法
通过 set
方法为字段设置依赖。
4.2 实现方式
将 Bean
注入到类的 set
方法中。
通过 set
方法注入依赖:
@Component
public class UserService {
private UserRepository userRepository;
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
4.3 优点
- 灵活,可以动态更改依赖。
4.4 缺点
- 不直观,不常用。
- 依赖变为可变状态,不安全。