一、常用的依赖注入方式有三种:
1、属性注入:基于注解@Autowired的依赖注入 (不推荐)
2.1 、构造器的依赖注入(推荐)
2.2 、构造器的依赖注入-lombok升级版(推荐)
3、setter注入(不推荐)
二、详细介绍
2.1 @Autowired的使用
例如:在构造器中使用到了@Autowired,因为构造器先执行,@Autowired后执行,所以此时是null
@RestController
@RequestMapping("/api/{edition}/page")
public class MyPageHelperController2 {
@Autowired
private UserService userService;
private String school;
public MyPageHelperController2(){
this.school = userService.getSchool();
}
}
解决方案1:将初始化操作后移。
@Autowired
private UserService userService;
public MyPageHelperController2() {
//userService.getSchool();
}
@PostConstruct //该注解标注的方法,会在构造函数、依赖注入之后执行,所以正确
public void init() {
userService.getSchool();
}
}
解决方案2:使用构造器注入
2.2.1 构造器注入(推荐)
@RestController
@RequestMapping("/api/{edition}/page2")
public class MyPageHelperController2 {
private UserService userService;
@Autowired
public MyPageHelperController2(UserService userService){
this.userService = userService;
}
}
在创建MyPageHelperController2对象的时候,通过参数形式,强制依赖UserService对象,确保创建MyPageHelperController2对象时每个对象都是有效状态。
2.2.2 构造器注入-lombok升级版(推荐)
@RequiredArgsConstructor(onConstructor=@_(@Autowired))
@RestController
@RequestMapping("/test")
public class TestController {
private final AService aService;
}
2.3 setter注入(不推荐)
@RestController
@RequestMapping("/test")
public class TestController {
private final AService aService;
@Autowired
public void setAService(AService aService){
this.aService = aService;
}
}
Spring Bean的三种依赖注入实现方式Spring可通过三种方式实现依赖注入
- 基于构造函数的依赖注入
- 基于Setter方法的依赖注入
- 以及基于Field的依赖注入
基于构造函数的依赖注入@Component
public class DemoBean{
public final DependencyBean dependencyBean;
public DemoBean(DependencyBean dependencyBean) {
this.dependencyBean = dependencyBean;
}
}基于构造函数注入的优点是,可以很方便地构造immutable的对象,将注入的字段声明为 final,在类实例化期间注入依赖。基于Setter方法的依赖注入@Component
public class DemoBean{
public DependencyBean dependencyBean;
@Autowired
public void setDependencyBean(DependencyBean dependencyBean) {
this.dependencyBean = dependencyBean;
}
}基于Setter方法注入的优点是,可以在实例Bean构造完成后注入,或者重新注入Bean,其中一个应用场景是通过JMX MBean进行管理。基于Field的依赖注入@Component
public class DemoBean{
@Autowired
private DependencyBean dependencyBean;
}Spring Framework官方已经不推荐这种依赖注入方法,文档中也去掉了相关的使用说明,编译器也会给出警告 Field injection is not recommended,究其原因,使用Field依赖注入时,有一些弊端:相比基于构造函数的依赖注入方式,基于Field的依赖注入无法构造immutable对象,因为如果将dependencyBean声明为final,则必须在构造函数中初始化。对单元测试不友好,如果没有对外的set接口,则很难替换mock bean
如何选择?
Spring官方推荐使用基于构造函数的依赖注入方式,结合final,可以构建immutable的对象,能够保证所有的依赖都不会为null。而当需要在实例Bean构造完成后注入,或者重新注入Bean时,选择使用Setter方法的注入方式。除此之外,当在Bean中使用模版方法,在Abstract类中注入依赖时,需要使用Setter方法注入。