大家好,我是编程小6,很高兴遇见你,有问题可以及时留言哦。
小知识,大挑战!本文正在参与“ 程序员必备小知识”创作活动
本文同时参与 掘力星计划,赢取创作大礼包,挑战创作激励金
使用IDEA开发时,同组小伙伴都喜欢用@Autowired注入,代码一片warning,看着很不舒服,@Autowired作为Spring的亲儿子,为啥在IDEA中提示了一个警告:Field injection is not recommended
想搞清楚这个问题之前,首先先了解一下依赖注入的几种方式
这种注入方式就是在bean的变量上使用注解进行依赖注入。本质上是通过反射的方式直接注入到field。这是我平常开发中看的最多也是最熟悉的一种方式。
@Autowired
UserDao userDao;
将各个必需的依赖全部放在带有注解构造方法的参数中,并在构造方法中完成对应变量的初始化,这种方式,就是基于构造方法的注入。比如:
final
UserDao userDao;
@Autowired
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
通过对应变量的setXXX()方法以及在方法上面使用注解,来完成依赖注入。比如:
private UserDao userDao;
@Autowired
public void setUserDao (UserDao userDao) {
this.userDao = userDao;
}
基于 field 的注入可能会带来一些隐含的问题。来我们举个例子:
@Autowired
private User user;
private String company;
public UserDaoImpl(){
this.company = user.getCompany();
}
编译过程不会报错,但是运行之后报NullPointerException
Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [...]: Constructor threw exception; nested exception is java.lang.NullPointerException
Java 在初始化一个类时,是按照静态变量或静态语句块 –> 实例变量或初始化语句块 –> 构造方法 -> @Autowired 的顺序。所以在执行这个类的构造方法时,user对象尚未被注入,它的值还是 null。
不能有效的指明依赖。相信很多人都遇见过一个bug,依赖注入的对象为null,在启动依赖容器时遇到这个问题都是配置的依赖注入少了一个注解什么的。这种方式就过于依赖注入容器了,当没有启动整个依赖容器时,这个类就不能运转,在反射时无法提供这个类需要的依赖。
依赖注入的核心思想之一就是被容器管理的类不应该依赖被容器管理的依赖,换成白话来说就是如果这个类使用了依赖注入的类,那么这个类摆脱了这几个依赖必须也能正常运行。然而使用变量注入的方式是不能保证这点的。
Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. 翻译过来就是: 强制依赖就用构造器方式
可选、可变的依赖就用setter注入
@Resource有2个属性name和type。在spring中name属性定义为bean的名字,type这是bean的类型。如果属性上加@Resource注解那么他的注入流程是
这种形式就是Spring推荐使用的构造器方式注入,此种方式是lombok包下的注解,如果使用此种方式,需要项目中引入lombok,例如:
@RequiredArgsConstructor
public class UserDaoImpl{
private final User user;
}