欢迎来到信息岛!
adminAdmin  2024-11-04 18:15 信息岛 显示边栏 |   抢沙发  24 
文章评分 0 次,平均分 0.0

SpringBoot_依赖注入的正确使用方式

引言

在使用IDEA开发时,很多码友都喜欢使用@Autowired注解进行依赖注入,这个时候 IDEA 就会报黄色警告,代码一片warning,为啥在IDEA中提示了这么一个警告呢?

image-20241104174056273

直接翻译一下

不建议直接在字段上进行依赖注入。

Spring官方建议:在Java Bean中永远使用构造方法进行依赖注入。

依赖注入的方式

Spring有三种依赖注入的方式

基于属性(filed)注入

这种注入方式就是在 bean 的变量上使用注解进行依赖注入。本质上是通过反射的方式直接注入到 field 。这是我平常开发中看的最多也是最熟悉的一种方式。比如:

@Autowired
private StudentServiceI studentService;

基于set方法注入

通过对应变量的setXXX()方法以及在方法上面使用注解,来完成依赖注入。比如:

private StudentServiceI studentService;

@Autowired
public void setStudentService(StudentServiceI studentService) {
    this.studentService = studentService;
}

基于构造器注入

将各个必需的依赖全部放在带有注解构造方法的参数中,并在构造方法中完成对应变量的初始化,这种方式,就是基于构造方法的注入。比如:

private StudentServiceI studentService;

@Autowired
public StudentController(StudentServiceI studentService) {
    this.studentService = studentService;
}

属性或set注入的问题

经过上面的对比,我们发现变量(filed)注入的方式是最简单的,也是唯一有警告,说不推荐的。这是为什么呢,我们来分析一下相关问题:

@Autowired
private StudentServiceI studentService;

public String name;

public StudentController(){
    this.name = studentService.getStuNameById(1);
}

编译过程不会报错,但是运行之后报NullPointerException

Cannot invoke "net.wanho.service.StudentServiceI.getNameById(int)" because "this.studentService" is null

Java 在初始化一个类时,是按照静态变量或静态语句块 –> 实例变量或初始化语句块 –> 构造方法 -> @Autowired 的顺序。所以在执行这个类的构造方法时,name对象尚未被注入,它的值还是 null。

因为@Autowired是在构造方法之后,上面的示例,无论是基于属性注入还是set方法注入都会报空指指针,所以在Spring新版本中推荐使用构造方法的方式注入

简化构造方法注入

使用Lombok的@RequiredArgsConstructor注解+final修改要注入的类型

加入依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.34</version>
</dependency>

简化注入

@RequiredArgsConstructor
public class StudentController {   
    private final StudentServiceI studentService;
}

原理说明

在Lombok中有三个关于构造方法的注解

  • @AllArgsConstructor : 创建所有参数的构造方法
  • @NoArgsConstructor : 创建空参数的构造方法
  • @RequiredArgsConstructor : 创建自定义参数的构造方法,要与@NoNull或final修饰,在这些修改的属性上,生成对应个数的构造方法

@NoArgsConstructor注解与@RequiredArgsConstructor注解是互斥的,只能二选一。

@Data
@AllArgsConstructor
@RequiredArgsConstructor
public class Student {
    private final Long id;
    private final String name;
    @NonNull
    private Integer age;
    @NonNull
    private String gender;
    private String address;
    private Date birth;
}

编译后的结果为

@Generated
    public Student(final Long id, final String name, final @NonNull Integer age, final @NonNull String gender, final String address, final Date birth) {
        if (age == null) {
            throw new NullPointerException("age is marked non-null but is null");
        } else if (gender == null) {
            throw new NullPointerException("gender is marked non-null but is null");
        } else {
            this.id = id;
            this.name = name;
            this.age = age;
            this.gender = gender;
            this.address = address;
            this.birth = birth;
        }
    }

    @Generated
    public Student(final Long id, final String name, final @NonNull Integer age, final @NonNull String gender) {
        if (age == null) {
            throw new NullPointerException("age is marked non-null but is null");
        } else if (gender == null) {
            throw new NullPointerException("gender is marked non-null but is null");
        } else {
            this.id = id;
            this.name = name;
            this.age = age;
            this.gender = gender;
        }
    }
「点点赞赏,手留余香」

还没有人赞赏,快来当第一个赞赏的人吧!

admin给Admin打赏
×
予人玫瑰,手有余香
  • 2
  • 5
  • 10
  • 20
  • 50
2
支付

声明:本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

admin
Admin 关注:0    粉丝:0
这个人很懒,什么都没写

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享