1. 先说结论
区别
- @noargsconstructor:生成无参的构造方法。
- @allargsconstructor:生成该类下全部属性的构造方法。
- @requiredargsconstructor:生成该类下被final修饰或者non-null字段生成一个构造方法。
场景
在springboot中,对于一个bean类,注入其他bean的时候,常见的是使用@autowired,实际上也可以使用构造函数注入,这个时候就可以使用@allargsconstructor或者@requiredargsconstructor来代替。
2. 代码解析区别
@noargsconstructor 默认都知道。
若不知道怎么查看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上区别
根据上面两个例子,我们可以看出无论是那种方法都可以注入bean属性对象,只是@requiredargsconstructor 是针对有条件的,没有什么区别。
但如果是下面的需求呢:
在该类下,部分字段还需要使用@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
@allargsconstructor例子:
@component
@tostring
@allargsconstructor
public class constructordemo {
private beantest1 beantest1;
@nonnull
private beantest2 beantest2;
private beantest3 beantest3;
@value("${constructor.name:hello}")
private string name;
}

@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. 总结
上面只是举例了代替@autowired的例子,实际上在json转化为对象,以及在spring中从配置文件读取配置使用@configurationproperties以及@constructorbinding的时候,都可以使用构造函数赋值,都可以用到上面的两个@allargsconstructor、@requiredargsconstructor。
具体:只要记得,那些字段需要赋值,就把它列进构造方法的参数里面即可。
好了,以上仅为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论