
本文已收录在Github,关注我,紧跟本系列专栏文章,咱们下篇再续!
用@Autowired时,发现IDEA报warning:

点击那三小点点:

再继续点:

Spring Team recommends "Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies".
和阿里编码规范推荐似的,Spring团队推荐又来了:总是在你的bean中使用构造函数建立依赖注入。总是使用断言强制依赖”。
直接alt+enter写成这样子
public final StuMapper stuMapper;
public StuServiceImpl(StuMapper stuMapper) {
this.stuMapper = stuMapper;
}为啥这就不警告了?@Autowired可对成员变量、方法以及构造方法三种方式操作。
成员变量和构造方法设置又有啥区别?@Autowired注入bean,相当于在配置文件中配置bean,且使用setter注入。而对构造方法,就相当于用构造函数进行依赖注入吧。莫非是这两种注入方法的不同???
看一段代码,能运行成功吗?
@Autowired
private User user;
private String school;
public UserAccountServiceImpl(){
this.school = user.getSchool();
}不能。因为Java类会先执行构造方法,再给@Autowired的user注入值。
Java变量的初始化顺序:静态变量或静态语句块–>实例变量或初始化语句块–>构造方法–>@Autowired
因此执行构造方法时报错:
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时构造方法出错,在构造方法里抛NPE。
通过构造方法注入
private User user;
private String school;
@Autowired
public UserAccountServiceImpl(User user) {
this.user = user;
this.school = user.getSchool();
}使用构造方法注入,可明确成员变量的加载顺序。
spring配置的bean的scope默认singleton,即启动后一直有。设置bean scope为prototype来声明该对象为动态创建。但若你的service本身是singleton,注入只执行一次。@Autowired本身就是单例模式,只会在程序启动时执行一次,即使不定义final也不会初始化第二次,所以这个final没意义吧。可能是为防止,在程序运行时,又执行一遍构造函数。
或者更易让人理解的,加上final只会在程序启动的时候初始化一次,且在程序运行的时候不会再改变。
Q:构造方法上的@Autowired是否可省略,构造方法本身就可注入吧,加这注解的目的是啥?
A:Spring4.x新增特性:若类只提供一个带参构造方法,则无需对其内部的属性写@Autowired,Spring自动为你注入属性。
若调用了有参构造,执行了注入。若没调用有参构造,就得加@Autowired注入,可避免没有调用构造方法导致的空指针。
参考: