依赖注入的三种方式:
- 基于字段注入
- 基于构造器注入
- 基于set方法注入
基于字段注入
@SpringBootTest
class AnnotationApplicationTests {
@Autowired
private EmployeeService employeeService;
}
优点:
- 注入方式简单:字段上附上注解@AutoWired即可。
- 可观性强:整体代码简洁明了。
缺点:
- 无法用于final修饰的变量
final类型的变量在调用class的构造函数的这个过程当中就得初始化完成,这个是基于字段的依赖注入做不到的地方,只能使用基于构造函数的依赖注入的方式.- 掩饰单一职责的设计思想
如果采用的是基于构造函数的依赖注入来使用Spring的IOC,当你注入的太多的时候,这个构造方法的参数就会很庞大,类似于下面。当你看到这个类的构造方法那么多参数的时候,你自然而然的会想一下:这个类是不是违反了单一职责思想?
但是使用基于字段的依赖注入不会让你察觉,你会很沉浸在@Autowire当中。- 与Spring的IOC机制紧密耦合
使用基于字段的依赖注入方式的时候,把控制权全给Spring的IOC了,别的类想重新设置下你的某个注入属性,没法处理(当然反射可以做到)。
本身Spring的目的就是解藕和依赖反转,结果通过再次与类注入器(在本例中为Spring)耦合,失去了通过自动装配类字段而实现的对类的解耦,从而使类在Spring容器之外无效.。
即对于IOC容器以外的环境,除了使用反射来提供它需要的依赖之外,无法复用该实现类。- 隐藏依赖性
当使用Spring的IOC的时,被注入的类应当使用public类型的方法(构造方法,setter类型方法)来向外界表达:我需要什么依赖。
但是基于字段的依赖注入的方式,基本都是private形式的,private把属性都给封印到class当中了。- 无法对注入的属性进行安全检查
在程序启动的时候无法拿到这个类,只有在真正的业务使用的时候才会拿到,若注入的是null,因为不调用将一直无法发现NullPointException的存在。
或者想在属性注入的时候,增加验证措施,也无法办到。
构造器注入
@RestController
public class EmployeeController {
private EmployeeService helloService;
@Autowired
public EmployeeController(EmployeeService helloService) {
this.helloService = helloService;
}
}
优点:
- 保证依赖不可变(final关键字)。
- 保证依赖不为空(省去了我们对其检查)。
- 保证返回客户端(调用)的代码的时候是完全初始化的状态。
- 避免了循环依赖。
- 提升了代码的可复用性。
- 可以明确成员变量的注入顺序。
缺点:
当注入参数较多时,代码臃肿。
set方法注入
@RestController
public class EmployeeController {
private EmployeeService helloService;
@Autowired
public void setHelloService(EmployeeService helloService) {
this.helloService = helloService;
}
}
优点:
- 相比构造器注入,set注入类似于选择性注入。
- 允许在类构造完成后重新注入。
缺点:
总结
- 通过上面,我们可以看到,基于字段的依赖注入方式有很多缺点,我们应当避免使用基于字段的依赖注入。
- 对于必需的依赖项,建议使用基于构造函数的注入,以使它们成为不可变的,并防止它们为null。
- 对于可选的依赖项,建议使用基于Setter的注入。
版权声明:本文为m0_46192140原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。