首页 > 其他分享 >Spring学习:AllArgsConstructor、RequiredArgsConstructor注入bean

Spring学习:AllArgsConstructor、RequiredArgsConstructor注入bean

时间:2024-05-27 11:45:19浏览次数:30  
标签:RequiredArgsConstructor String Spring private public AllArgsConstructor final ap

@NoArgsConstructor、@AllArgsConstructor、@RequiredArgsConstructor(搭配@FieldDefaults、@NonFinal)的区别以及在springboot常用地方

 

注解解释、区别:

@NoArgsConstructor:生成无参的构造方法。
@AllArgsConstructor:生成该类下全部属性的构造方法。(主讲)
@RequiredArgsConstructor:生成该类下被final修饰或者带有@non-null的构造方法。(主讲)

代码解析区别:

1. @AllArgsConstructor

@AllArgsConstructor
public class Student{

    private String name;

    // 被final修饰
    private final String age;

    @NonNull
    private String sex;
}

根据反编译查看代码(反编译工具jad的使用可点击此处查看):

public class Student
{

    public Student(String name, String age, String sex)
    {
        if(sex == null)
        {
            throw new NullPointerException("sex is marked non-null but is null");
        } else
        {
            this.name = name;
            this.age = age;
            this.sex = sex;
            return;
        }
    }

    private String name;
    private final String age;
    private String sex;
}

结果:默认只要是该类下的字段,无论什么修饰,都会被参与构造。

2. @RequiredArgsConstructor

@RequiredArgsConstructor
public class Student
{
    private String name;

    // 被final修饰
    private final String age;

    @NonNull
    private String sex;
}

根据反编译查看代码:

public class Student
{

    public Student(String age, String sex)
    {
        if(sex == null)
        {
            throw new NullPointerException("sex is marked non-null but is null");
        } else
        {
            this.age = age;
            this.sex = sex;
            return;
        }
    }

    private String name;
    private final String age;
    private String sex;
}

结果:只构造了有final或者@no-null修饰的字段。

场景:

在springboot中,对于一个bean类,注入其他bean的时候,常见的是使用@Autowired,实际上也可以使用构造函数注入,这个时候就可以使用@AllArgsConstructor或者@RequiredArgsConstructor来代替。

场景使用—代替@Autowired注入bean对象:

1. @AllArgsConstructor

@Component
public class BeanTest1
{
}

@Component
public class BeanTest2
{
}

@Component
public class BeanTest3
{
}

//Controller层
@RestController
@ToString
@AllArgsConstructor
public class BeanTestController
{
    // 注入三个bean对象,完全没有使用Autowired注解
    private BeanTest1 beanTest1;

    @NonNull
    private BeanTest2 beanTest2;

    private final BeanTest3 beanTest3;
}

//测试类
@Component
public class ConstructorRunner implements ApplicationRunner
{

    @Autowired
    BeanTestController beanTestController;

    @Override
    public void run(ApplicationArguments args) throws Exception
    {
        System.out.println(beanTestController);
    }
}

结果:完完全全可以注入bean对象。

2. @RequiredArgsConstructor

//Controller层,换成@RequiredArgsConstructor
@RestController
@ToString
@RequiredArgsConstructor
public class BeanTestController
{
    // 注入三个bean对象,完全没有使用Autowired注解
    private BeanTest1 beanTest1;

    @NonNull
    private BeanTest2 beanTest2;

    private final BeanTest3 beanTest3;
}


结果:由图可以看出,没有被修饰final或者@no-null的属性无法被注入,因此,建议使用@RequiredArgsConstructor的时候,对需要的字段加上final修饰。
注:强调对需要的字段,为什么要强调,请看下面的例子:

3. @RequiredArgsConstructor 与 @AllArgsConstructor 在注入bean上的区别

根据上面两个例子,我们可以看出无论是那种方法都可以注入bean属性对象,只是@RequiredArgsConstructor 是针对有条件的,没有什么区别。

但如果是下面的需求呢:
在该类下,部分字段还需要使用@Value来注入值呢?

使用@AllArgsConstructor

@RestController
@ToString
@AllArgsConstructor
public class BeanTestController
{
    // 注入三个bean对象,完全没有使用Autowired注解
    private BeanTest1 beanTest1;

    @NonNull
    private BeanTest2 beanTest2;

    private final BeanTest3 beanTest3;

    @Value("${constructor.name:hello}")
    private String name;
}

出现以下报错:

使用@RequiredArgsConstructor

//Controller层,换成@RequiredArgsConstructor
@RestController
@ToString
@RequiredArgsConstructor
public class BeanTestController
{
    // 注入三个bean对象,完全没有使用Autowired注解
    private BeanTest1 beanTest1;

    @NonNull
    private BeanTest2 beanTest2;

    private final BeanTest3 beanTest3;

    @Value("${constructor.name:hello}")
    private String name;
}

结论:
一个bean如果使用构造函数进行bean属性注入,那么当然构造函数不能加上name。
因为加上,在创建ConstructorDemo该bean的时候,需要找类型为String,名字是name的bean对象,当然是不存在,必然会报错。
因此,当然不能使用@AllArgsConstructor了,只能使用@RequiredArgsConstructor

总结:

上面只是举例了代替@Autowired的例子,实际上在json转化为对象,以及在spring中从配置文件读取配置使用@ConfigurationProperties以及@ConstructorBinding的时候,都可以使用构造函数赋值,都可以用到上面的两个@AllArgsConstructor、@RequiredArgsConstructor。
具体:只要记得,那些字段需要赋值,就把它列进构造方法的参数里面即可。

拓展:

@RequiredArgsConstructor搭配@FieldDefaults、@NonFinal。

注解解释:
@FieldDefaults:可以为被注解的类或枚举中的每个字段添加访问修饰符(public, private, 或 protected)。它还可以为注释的类或枚举中的每个字段添加final。
参数介绍:
添加访问修饰符:level=AccessLevel.PRIVATE(其余可填写PUBLIC,MODULE,PROTECTED,PACKAGE,PRIVATE,NONE),默认是NONE
添加final:makeFinal=true(默认是false关闭)。
注意:任何必须保持非final的字段可以用@NonFinal(也在lombok.experimental包中)来注释。

@NonFinal:作用于类、变量,表示变量不加 final。

@RequiredArgsConstructor和@FieldDefaults搭配使用

@RestController
@ToString
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true)
public class BeanTestController
{
    private BeanTest1 beanTest1;

    private BeanTest2 beanTest2;

    private BeanTest3 beanTest3;
}


反编译后代码,可以看出都加了final:

public class BeanTestController
{

    public String toString()
    {
        return (new StringBuilder()).append("BeanTestController(beanTest1=").append(beanTest1).append(", beanTest2=").append(beanTest2).append(", beanTest3=").append(beanTest3).append(")").toString();
    }

    public BeanTestController(BeanTest1 beanTest1, BeanTest2 beanTest2, BeanTest3 beanTest3)
    {
        this.beanTest1 = beanTest1;
        this.beanTest2 = beanTest2;
        this.beanTest3 = beanTest3;
    }

    private final BeanTest1 beanTest1;
    private final BeanTest2 beanTest2;
    private final BeanTest3 beanTest3;
}

结果:注入成功

通过上面可以看出,@FieldDefaults(makeFinal = true)会为每个字段添加final,然后@RequiredArgsConstructor注入,但是如果在该类下,部分字段还需要使用@Value来注入值呢?
代码:

@RestController
@ToString
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true)
public class BeanTestController
{
    private BeanTest1 beanTest1;

    private BeanTest2 beanTest2;

    private BeanTest3 beanTest3;

    @Value("${constructor.name:hello}")
    private String name;
}

反编译后代码:

public class BeanTestController
{

    public String toString()
    {
        return (new StringBuilder()).append("BeanTestController(beanTest1=").append(beanTest1).append(", beanTest2=").append(beanTest2).append(", beanTest3=").append(beanTest3).append(", name=").append(name).append(")").toString();
    }

    public BeanTestController(BeanTest1 beanTest1, BeanTest2 beanTest2, BeanTest3 beanTest3, String name)
    {
        this.beanTest1 = beanTest1;
        this.beanTest2 = beanTest2;
        this.beanTest3 = beanTest3;
        this.name = name;
    }

    private final BeanTest1 beanTest1;
    private final BeanTest2 beanTest2;
    private final BeanTest3 beanTest3;
    private final String name;
}


结果:注入失败,出现报错,
结论:
一个bean如果使用构造函数进行bean属性注入,那么当然构造函数不能加上name。
因为加上,在创建ConstructorDemo该bean的时候,需要找类型为String,名字是name的bean对象,当然是不存在,必然会报错。
因此,要用@NonFinal,不让使用@value注入的值被创建ConstructorDemo该bean时使用

@RequiredArgsConstructor和@FieldDefaults、@NonFinal搭配使用

代码:

@RestController
@ToString
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true)
public class BeanTestController
{
    private BeanTest1 beanTest1;

    private BeanTest2 beanTest2;

    private BeanTest3 beanTest3;

    @NonFinal
    @Value("${constructor.name:hello}")
    private String name;
}


反编译后代码:

public class BeanTestController
{

    public String toString()
    {
        return (new StringBuilder()).append("BeanTestController(beanTest1=").append(beanTest1).append(", beanTest2=").append(beanTest2).append(", beanTest3=").append(beanTest3).append(", name=").append(name).append(")").toString();
    }

    public BeanTestController(BeanTest1 beanTest1, BeanTest2 beanTest2, BeanTest3 beanTest3)
    {
        this.beanTest1 = beanTest1;
        this.beanTest2 = beanTest2;
        this.beanTest3 = beanTest3;
    }

    private final BeanTest1 beanTest1;
    private final BeanTest2 beanTest2;
    private final BeanTest3 beanTest3;
    private String name;
}

结果:注入成功

引用:
https://www.ab62.cn/article/11041.html
https://blog.csdn.net/qq_31635851/article/details/122123278

标签:RequiredArgsConstructor,String,Spring,private,public,AllArgsConstructor,final,ap
From: https://www.cnblogs.com/zhihongShee/p/18215174

相关文章

  • 1915springboot VUE 宠物寄养平台系统开发mysql数据库web结构java编程计算机网页源码m
    一、源码特点 springbootVUE宠物寄养平台系统是一套完善的完整信息管理类型系统,结合springboot框架和VUE完成本系统,对理解JSPjava编程开发语言有帮助系统采用springboot框架(MVC模式开发),系统具有完整的源代码和数据库,系统主要采用B/S模式开发。springbootVUE宠物寄养......
  • 【Spring】使用Spring常用导入依赖介绍
    当使用Spring框架时,以下是常用导入的依赖的详细介绍,按照不同的功能和类别进行分点表示和归纳:1、核心依赖SpringCore(spring-core)功能:提供了Spring框架的基础功能,包括IoC(控制反转)和DI(依赖注入)的基础支持。重要性:Spring框架的基石,任何Spring项目都需要。SpringBeans(spri......
  • 【Spring】SpringMVC中@RequestMapping 详解
    1、简介在SpringMVC中,@RequestMapping是一个非常重要的注解,它用于映射web请求(如HTTP请求)到特定的处理器方法或处理器类。2、基本用法@RequestMapping可以标注在方法或类上。当标注在类上时,它提供了初步的请求映射信息,如请求路径的前缀。当标注在方法上时,它提供了具体的......
  • springboot宠物领养管理系统论文
    目录摘要IAbstractII第1章绪论31.1项目研究的背景31.2开发目的和意义31.3国内外研究现状4第2章系统开发工具52.1Java编程语言52.2B/S模式52.3MySQL数据库62.4后端框架介绍72.4.1SpringBoot介绍72.4.2Mybatis介绍72.4.3SpringMvc介......
  • Spring学习:如何创建并配置一个第三方Bean
    文章目录一、知识储备二、创建第三方Bean 一、知识储备使用XML配置application.xml<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSche......
  • 【JAVA】Java如何使用Spring Boot进行Web服务开发
    文章目录前言一、函数解释二、代码实现三、总结前言在现代的微服务架构中,创建快速、可靠的Web服务已经成为一项基本技能。SpringBoot是一个出色的框架,它简化了Spring应用开发,使我们能够更快速地创建和部署Web服务。在这篇博客中,我们将探讨如何使用Java和SpringBoo......
  • SpringValidation
    一、概述:​JSR303中提出了BeanValidation,表示JavaBean的校验,HibernateValidation是其具体实现,并对其进行了一些扩展,添加了一些实用的自定义校验注解。​Spring中集成了这些内容,你可以在Spring中以原生的手段来使用校验功能,当然Spring也对其进行了一点简单的扩展,以便其更适......
  • Java项目-基于springboot+vue的旅游管理系统(源码+数据库+文档)​
    如需完整项目,请私信博主基于SpringBoot+Vue的旅游管理系统开发语言:Java数据库:MySQL技术:SpringBoot+MyBatis+Vue.js工具:IDEA/Ecilpse、Navicat、Maven随着科学技术的飞速发展,网络快速发展、人民生活的快节奏都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,旅游管......
  • Java项目-基于springboot+vue的简历系统(源码+数据库+文档)​
    如需完整项目,请私信博主基于SpringBoot+Vue的简历系统开发语言:Java数据库:MySQL技术:SpringBoot+MyBatis+Vue.js工具:IDEA/Ecilpse、Navicat、Maven随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,简历系统当然也不......
  • Spring Cloud快速入门
    SpringCloud是一个基于SpringBoot的微服务框架,它提供了一系列的功能和工具,用于构建分布式系统和服务。以下是一个SpringCloud应用框架的快速入门指南:1.环境准备安装JavaJDK:确保你的计算机上安装了JavaDevelopmentKit(JDK)。安装Maven或Gradle:Maven和Gradle是Java......