@AllArgsConstructor、@NoArgsConstructor、@RequiredArgsConstructor的区别以及在springboot常用地方

1. 先说结论

  1. 区别:
    @NoArgsConstructor:生成无参的构造方法。
    @AllArgsConstructor:生成该类下全部属性的构造方法。
    @RequiredArgsConstructor:生成该类下被final修饰或者non-null字段生成一个构造方法。
  2. 场景:
    在springboot中,对于一个bean类,注入其他bean的时候,常见的是使用@Autowired,实际上也可以使用构造函数注入,这个时候就可以使用@AllArgsConstructor或者@RequiredArgsConstructor来代替

2. 代码解析区别

  1. @NoArgsConstructor 默认都知道。
  2. 若不知道怎么查看java反编译字节码内容,可以看一下:
    Java 如何进行反编译生成.java文件(javap、jad下载安装使用)

1. @AllArgsConstructor

@AllArgsConstructor
public class demo {

    private String name;

    // 被final修饰
    private final String age;

    @NonNull
    private String sex;
}

根据反编译查看代码:

public class demo
{
	// 默认 只要是该类下的字段,无论什么修饰,都会被参与构造
    public demo(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 demo {

    private String name;

    // 被final修饰
    private final String age;

    @NonNull
    private String sex;
}

反编译代码:

public class demo
{
	// 只构造了有final或者no-null修饰的字段
    public demo(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;
}

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

1. @AllArgsConstructor

根据上面看反编译代码可以得出:只要是类里面字段,都会被加入到构造函数里面,不管被什么修饰。

例子:

@Component
public class BeanTest1 {
}

@Component
public class BeanTest2 {
}

@Component
public class BeanTest3 {
}

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

    @NonNull
    private BeanTest2 beanTest2;

    private final BeanTest3 beanTest3;
}

// 这只是个测试类
@Component
public class ConstructorRunner implements ApplicationRunner {

    @Autowired
   ConstructorDemo ConstructorDemo;

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

完完全全可以注入bean对象。

2. @RequiredArgsConstructor

RequiredArgsConstructor:只会构造被final修饰或者no-null修饰的字段。

// 改成@RequiredArgsConstructor
@Component
@RequiredArgsConstructor
@ToString
public class ConstructorDemo {

    private BeanTest1 beanTest1;

    @NonNull
    private BeanTest2 beanTest2;

    private final BeanTest3 beanTest3;
}

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

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

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

  2. 但如果是下面的需求呢:

    在该类下,部分字段还需要使用@Value来注入值呢?

    @Component
    @ToString
    public class ConstructorDemo {
    
        private BeanTest1 beanTest1;
    
        @NonNull
        private BeanTest2 beanTest2;
    
        private BeanTest3 beanTest3;
    
        @Value("${constructor.name:hello}")
        private String name;
        
    }
    
    先思考一下:
    一个bean如果使用构造函数进行bean属性注入,那么当然构造函数不能加上name。
    因为加上,在创建ConstructorDemo该bean的时候,需要找类型为String,名字是name的bean对象,当然是不存在,必然会报错。
    因此,当然不能使用@AllArgsConstructor了,只能使用@RequiredArgsConstructor
    

    3.@AllArgsConstructor例子:

    @Component
    @ToString
    @AllArgsConstructor
    public class ConstructorDemo {
    
        private BeanTest1 beanTest1;
    
        @NonNull
        private BeanTest2 beanTest2;
    
        private BeanTest3 beanTest3;
    
        @Value("${constructor.name:hello}")
        private String name;
    }
    

    4.@RequiredArgsConstructor的例子

    @Component
    @ToString
    @RequiredArgsConstructor
    public class ConstructorDemo {
    	// 肯定为null,因为没有final或者no-null修饰
        private BeanTest1 beanTest1;
    
        @NonNull
        private BeanTest2 beanTest2;
    
        private final BeanTest3 beanTest3;
    
        @Value("${constructor.name:hello}")
        private String name;
    }
    

    4. 总结

  3. 上面只是举例了代替@Autowired的例子,实际上在json转化为对象,以及在spring中从配置文件读取配置使用@ConfigurationProperties以及@ConstructorBinding的时候,都可以使用构造函数赋值,都可以用到上面的两个@AllArgsConstructor、@RequiredArgsConstructor。

  4. 具体:只要记得,那些字段需要赋值,就把它列进构造方法的参数里面即可。
  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码蒋

您的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值