Spring中实现依赖注入(DI)的三种方式
1. @Autowired
字段注入(不推荐)
@Service
public class UserService {@Autowired // 直接在字段上注入private UserRepository userRepository;
}
原理:Spring 启动时扫描所有 @Component
、@Service
等注解的类,发现 @Autowired
字段后,自动从容器中查找匹配的 Bean 并注入。
2. Setter 注入(不推荐)
@Service
public class UserService {private UserRepository userRepository;@Autowired // 在 setter 方法上注入public void setUserRepository(UserRepository userRepository) {this.userRepository = userRepository;}
}
原理:Spring 扫描到 @Autowired
标记的 Setter 方法后,自动调用该方法注入依赖。
3. 构造函数注入(推荐)
3.1 手动构造函数
@Service
public class UserService {private final UserRepository userRepository; // final 确保不可变// 手动编写构造函数public UserService(UserRepository userRepository) {this.userRepository = userRepository;}
}
原理:
- Spring 通过反射调用构造函数,自动注入依赖。
- Spring 4.3+ 后,如果类只有一个构造函数,可以省略
@Autowired
(Spring 会自动识别)。
3.2 构造函数 + @RequiredArgsConstructor
(Lombok)(强烈推荐)
@Service
@RequiredArgsConstructor // Lombok 自动生成构造函数
public class UserService {private final UserRepository userRepository; // final 确保不可变
}
原理:
- Lombok 的
@RequiredArgsConstructor
会自动生成一个包含所有final
字段和@NonNull
字段的构造函数。 - Spring 会自动调用这个构造函数注入依赖(无需
@Autowired
)。
总结
特性 | @Autowired 字段注入 | Setter 注入 | 构造函数注入 | 构造函数 + @RequiredArgsConstructor |
---|---|---|---|---|
代码简洁性 | ⭐⭐⭐⭐(最简洁) | ⭐⭐⭐ | ⭐⭐(需手动写构造函数) | ⭐⭐⭐⭐(Lombok 自动生成) |
可读性 | ⭐(依赖关系隐藏) | ⭐⭐(setter 分散) | ⭐⭐⭐⭐(构造函数明确) | ⭐⭐⭐⭐(和手动构造函数一样清晰) |
可测试性 | ❌(难以测试) | ⭐⭐(需手动注入) | ⭐⭐⭐⭐(直接传入 mock) | ⭐⭐⭐⭐(和手动构造函数一样) |
不可变性(final) | ❌(不支持) | ❌(不支持) | ⭐⭐⭐⭐(支持) | ⭐⭐⭐⭐(支持) |
Spring 推荐程度 | ❌(不推荐) | ⭐(仅可选依赖) | ⭐⭐⭐⭐(推荐) | ⭐⭐⭐⭐(推荐) |
是否需要 Lombok | ❌ | ❌ | ❌ | ⭐⭐⭐⭐(依赖 Lombok) |