使用@RequiredArgsConstructor替换@Autowired和@Resource
引言
楼主最开始是使用@Autowired进行依赖注入,但是IDEA中直接在变量上使用 @Autowired会发现警告提示:Field injection is not recommended
为什么会出现这种提示?
原因是官方建议我们使用构造器注入方式
这种方式存在明显的弊端,比如:注入对象不能用final修饰、无法发现NullPointException的存在。
为什么Spring官方推荐使用构造器注入
有几种注入方式
属性注入
在bean的变量上使用注解进行依赖注入。本质上是通过反射的方式直接注入到field。
@Component
public class Person {
// 属性注入
@Autowired
private Pet pet;
}
@Component
class Pet {
private String name;
}
好处:
美观、大方,只需要一个注解 @Autowired 就可以完成注入。
缺点:
Setter 方法注入
通过对应变量的setXXX()
方法以及在方法上面使用注解,来完成依赖注入。(会在bean实例化之后调用该方法)
@Component
public class Person {
private Pet pet;
public Pet getPet() {
return pet;
}
@Autowired
public void setPet(Pet pet) {
this.pet = pet;
}
}
@Component
class Pet {
private String name;
}
好处:灵活,可以在类实例化后,重新注入。
构造器注入
@Component
public class Person {
private final Pet pet;
@Autowired // 只有一个构造方法可以省略
public Person(Pet pet) {
this.pet = pet;
}
public Pet getPet() {
return pet;
}
}
@Component
class Pet {
private String name;
}
好处:
-
组件能用final修饰,保证注入的组件不可变且不为空
-
保证使用构造器注入的类呈完全初始化的状态
-
能够避免循环依赖
推荐的原因
主要有两个
-
类的属性能用final修饰,保证了注入组件的不可变
-
能够避免循环依赖的问题
说明:
使用@Autowired本质是通过反射注入属性,所以不能用final修饰
使用final修饰属性好处:
不可变性:final修饰的属性一旦被赋值后就不能再被修改,可以保证对象的属性在被初始化后不会被意外地修改,提高了代码的可维护性和健壮性。
线程安全:由于final属性是不可变的,因此在多线程环境下可以避免竞态条件,从而保证线程安全性。
JIT优化:final修饰的属性在编译期间就可以确定它的值,因此JIT编译器可以在代码运行之前进行优化,提高代码的执行效率。
能够避免循环依赖问题:
使用构造器注入,所有的依赖项都需要一次性地传入,当没有某个bean的时候会抛出异常
@RequiredArgsConstructor是什么
是lombok的一个注解,作用于类,用于生成包含 final 和 @NonNull 注解的成员变量的构造方法
可以自动生成构造器注入的代码