1、spring提供了三种依赖注入的方式,先来看一下各个注入方式的实现方法以及各自的优缺点

1)基于字段注入的方式

  该方式使用@Autowired方法就可以实现类的注入

@Component
public class ClassB {

    @Autowired
    private ClassA classA;

    public void testMethod1() {
        classA.method1();
    }
}

这种注入方式的优点就是实现简单,通过一个注解就可以完成注入。但是这样的弊端却有很多,是最不推荐的一种注入方式。

  1. 当ClassA没有被Spring管理时,则通过@Autowrite注解注入的ClassA则是null,此时调用A的方法会出现空指针异常。而且脱离了容器环境就不能够使用独立的使用ClassB中的ClassA对象,比如代码段:
ClassB classB = new ClassB();
classB.classA.method1();
  1.  无法注入一个final类型的属性,这是由于final类型的字段必须在类实例化的时候进行实例化,而Spring的属性注入是在实例化完成之后通过AbstractAutowireCapableBeanFactory#populateBean方法进行属性填充的

spring使用注解构造器和setter注入_构造方法

  1. 第三点也是最容易忽略的一点,在存在循环依赖问题时,通过@Autowrite方式进行注入时,项目编译不会报错,但是调用循环依赖的方法时则会报错。所以@Autowrite方式不是解决了循环依赖的问题而是将问题隐藏了,这样更致命。 

spring使用注解构造器和setter注入_java_02

 2)基于构造方法的方式进行注入

@Component
public class ClassB {

    private final ClassA classA;

    @Autowired
    public ClassB(ClassA classA) {
        this.classA = classA;
    }

    public void testMethod1() {
        classA.method1();
    }
}

通过对比上一种方法的缺点,我们看一下通过构造方法注入的优点。

  1. 通过构造方法注入可以脱离Spring框架使用注入的类,下面那段代码不会报空指针异常
ClassB classB = new ClassB(new ClassA());
classB.testMethod1();
  1.  可以注入final类型的属性,并且能够保证注入的属性都不为空
  2. 如果出现循环依赖的情况,通过该构造方法注入的方式注入的时候编译期间就会报异常
  3. 缺点就是如果注入的类比较多,或者有的类不是强制需要的时候就会增加构造方法的复杂度

3)set方法注入

@Component
public class ClassB {

    private ClassA classA;

    @Autowired
    public void setClassA(ClassA classA) {
        this.classA = classA;
    }

    public void testMethod1() {
        classA.method1();
    }
}
  1. 通过set方法进行注入的时候可以对依赖进行按需注入,避免了构造方法注入的时候许多依赖注入时候的问题
  2. set方法注入可以多次重复注入
  3. set方法注入不会发生循环依赖问题