Spring的强大我们都知道,这里就遇到的一个疑问写一篇文章。
我们都知道:@Autowired 可以对成员变量、方法以及构造函数进行注释。那么对成员变量和构造函数进行注释又有什么区别呢?
一、下面先看下实例:
public class Test{
//方式一:用在成员变量上
@Autowired
private A a;
//方式二:用在构造函数上---推荐
private final B b;
@Autowired
public Test(B b) {
this.b = b;
}
}
在使用Sring的@Autowired注解时,你可能会收到如下提醒:
Spring Team recommends “Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies”.
翻译:Spring Team建议“在bean中始终使用基于构造函数的依赖项注入。总是对强制依赖项使用断言”。
注意:断言,Java基础的一个内容,具体内容可以参考《java学习笔记之断言(Assertion)》。
理解:
方式一:
@Autowired写在成员变量上,相当于在配置文件中配置bean,并且使用setter注入。
方式二:
@Autowired写在构造函数上,相当于使用构造函数进行依赖注入。
二、再来个实例:
public class Test{
@Autowired
private A a;
private String prefix;
public Test(A a) {
this.prefix= a.getExcelPrefix();
}
}
上面这种情况就会报错了,报错信息可能会像下面:
Exception in thread “main” org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘…’ defined in file […class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate […]: Constructor threw exception; nested exception is java.lang.NullPointerException
报错信息说:
创建Bean时出错,出错原因是实例化bean失败,因为bean时构造方法出错,在构造方法里抛出了空指针异常。
三、总结:
区别主要在于加载顺序上,@autowired写在变量上的注入要等到类完全加载完,才会将相应的bean注入,而变量是在加载类的时候按照相应顺序加载的,所以变量的加载要早于@autowired变量的加载,那么给变量prefix 赋值的时候所使用的a,其实还没有被注入,所以报空指针,而使用构造器就在加载类的时候将a加载了,这样在内部使用a给prefix 赋值就完全没有问题。
Java变量的初始化顺序为:
静态变量或静态语句块–>实例变量或初始化语句块–>构造方法中的变量–>@Autowired下的变量
该内容在我的另一篇文章中也有简单提及《小码农的十万个为什么!!!(持续更新)》
以梦为马,以汗为泉,不忘初心,不负韶华。