引言
应用 IDEA 开发时,同组小伙伴都喜爱用 @Autowired 注入,代码一片 warning,看着很不难受,@Autowired 作为 Spring 的亲儿子,为啥在 IDEA 中提醒了一个正告:Field injection is not recommended
想搞清楚这个问题之前,首先先理解一下依赖注入的几种形式
Spring 的三种注入形式
属性(filed)注入
这种注入形式就是在 bean 的变量上应用注解进行依赖注入。实质上是通过反射的形式间接注入到 field。这是我平时开发中看的最多也是最相熟的一种形式。
@Autowired
UserDao userDao;
复制代码
结构器注入
将各个必须的依赖全副放在带有注解构造方法的参数中,并在构造方法中实现对应变量的初始化,这种形式,就是基于构造方法的注入。比方:
final
UserDao userDao;
@Autowired
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
复制代码
set 办法注入
通过对应变量的 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,在启动依赖容器时遇到这个问题都是配置的依赖注入少了一个注解什么的。这种形式就过于依赖注入容器了,当没有启动整个依赖容器时,这个类就不能运行,在反射时无奈提供这个类须要的依赖。java 培训
问题三
依赖注入的核心思想之一就是被容器治理的类不应该依赖被容器治理的依赖,换成文言来说就是如果这个类应用了依赖注入的类,那么这个类解脱了这几个依赖必须也能失常运行。然而应用变量注入的形式是不能保障这点的。
spring 倡议
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 代替 @Autowired
@Resource 有 2 个属性 name 和 type。在 spring 中 name 属性定义为 bean 的名字,type 这是 bean 的类型。如果属性上加 @Resource 注解那么他的注入流程是
如果同时指定了 name 和 type,则从 Spring 上下文中找到惟一匹配的 bean 进行拆卸,找不到则抛出异样。
如果指定了 name,则从上下文中查找名称匹配的 bean 进行拆卸,找不到则抛出异样。
如果指定了 type,则从上下文中找到类型匹配的惟一 bean 进行拆卸,找不到或是找到多个,都会抛出异样。
如果既没有指定 name,又没有指定 type,则默认依照 byName 形式进行拆卸;如果没有匹配,依照 byType 进行拆卸。
@Autowired 只依据 type 进行注入,不会去匹配 name。如果波及到 type 无奈分别注入对象时,那须要依赖 @Qualifier 或 @Primary 注解一起来润饰。
应用 @RequiredArgsConstructor 结构器形式注入
这种模式就是 Spring 举荐应用的结构器形式注入,此种形式是 lombok 包下的注解,如果应用此种形式,须要我的项目中引入 lombok,例如:
@RequiredArgsConstructor
public class UserDaoImpl{
private final User user;
}