[Field injection is not recommended]为什么Spring的@Autowire不推荐注解在属性上?

[Field injection is not recommended]为什么Spring的@Autowire不推荐注解在属性上?

背景

大家都知道spring中的bean可以使用@Autowire注解进行自动装配注入。其中有三种方式:

  • Constructor-based dependency injection 基于构造函数的依赖注入

  • Setter-based dependency injection 基于setter方法的依赖注入

  • Field-based dependency injection 基于属性字段的依赖注入

但是在Idea中,使用基于属性的注入(代码示例如下),会吃到“黄牌”warning

 @Autowire
private JdbcTemplate jdbcTemplate

warning信息:

Field injection is not recommended

Spring Team recommends: "Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies".

为什么不推荐使用属性注入?

  1. 属性注入字段不允许用final修饰

基于属性字段的注入得到的bean不允许声明为final类型。只能通过基于构造函数的注入来声明不可变的bean(immutable bean)。

  1. 违反单一原则

如果过多地使用属性注入,很容易写很多个bean进行装配。而使用构造注入时,bean作为构造函数的参数,如果数量太多,更容易让人发现该类包含了太多协作者(违反了单一原则),进而将类拆分为更小、更易于维护的碎片。

  1. 和spring的IOC机制紧耦合

当你使用基于字段的依赖注入方式,完全把控制权全给Spring的IOC机制,在Spring容器之外,其它类无法重新设置某个注入的属性bean(反射机制除外)。

  1. 不方便对注入的bean进行校验

基于字段的依赖注入方式,类构造时并没有拿到被注入的属性的值,只有在被业务使用的时候才会拿到,不方便对该属性进行校验。假如使用构造注入,就可以在构造函数中进行校验,比如非空校验(避免NPE)。当然使用Spring的校验注解也可以实现。

  1. 隐藏了依赖关系

当你使用Spring的IOC的时候,被注入的类应当使用一些public类型(构造方法,和setter类型方法)的方法来向外界表达:我需要什么依赖。基于字段的依赖注入的方式,基本都是private形式的,外界不易理解所有依赖关系。

结论

避免使用基于字段的依赖注入,推荐使用基于构造函数基于setter的依赖注入。对于必需的依赖项,建议使用基于构造函数的注入,并声明为final类型,同时可以在构造函数中校验防止它们为null。对于可选的依赖项,建议使用基于Setter的注入

参考

Field injection is not recommended – Spring IOC

你可能感兴趣的:([Field injection is not recommended]为什么Spring的@Autowire不推荐注解在属性上?)