使用@RequiredArgsConstructor替换@Autowired和@Resource

659 阅读2分钟

使用@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修饰属性好处:

  1. 不可变性:final修饰的属性一旦被赋值后就不能再被修改,可以保证对象的属性在被初始化后不会被意外地修改,提高了代码的可维护性和健壮性。

  2. 线程安全:由于final属性是不可变的,因此在多线程环境下可以避免竞态条件,从而保证线程安全性。

  3. JIT优化:final修饰的属性在编译期间就可以确定它的值,因此JIT编译器可以在代码运行之前进行优化,提高代码的执行效率。

能够避免循环依赖问题:

使用构造器注入,所有的依赖项都需要一次性地传入,当没有某个bean的时候会抛出异常

@RequiredArgsConstructor是什么

是lombok的一个注解,作用于类,用于生成包含 final 和 @NonNull 注解的成员变量的构造方法

可以自动生成构造器注入的代码