- 1. 先说结论
- 2. 代码解析区别
- 1. @AllArgsConstructor
- 2. @RequiredArgsConstructor
- 3. 场景使用---代替@Autowired注入bean对象
- 1. @AllArgsConstructor
- 2. @RequiredArgsConstructor
- 3. @RequiredArgsConstructor 与 @AllArgsConstructor 在注入bean上的区别
- 4. 总结
- 区别:
@NoArgsConstructor:生成无参的构造方法。
@AllArgsConstructor:生成该类下全部属性的构造方法。
@RequiredArgsConstructor:生成该类下被final修饰或者non-null字段生成一个构造方法。 - 场景:
在springboot中,对于一个bean类,注入其他bean的时候,常见的是使用@Autowired,实际上也可以使用构造函数注入,这个时候就可以使用@AllArgsConstructor或者@RequiredArgsConstructor来代替。
- @NoArgsConstructor 默认都知道。
- 若不知道怎么查看java反编译字节码内容,可以看一下:
Java 如何进行反编译生成.java文件(javap、jad下载安装使用)
@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;
}
这是源码的英文解释:
根据上面看反编译代码可以得出:只要是类里面字段,都会被加入到构造函数里面,不管被什么修饰。
例子:
@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对象。
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修饰。注:强调 对需要的字段,为什么要强调,请看下面的例子:
-
根据上面两个例子,我们可以看出无论是那种方法都可以注入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; }
- 上面只是举例了代替@Autowired的例子,实际上在json转化为对象,以及在spring中从配置文件读取配置使用@ConfigurationProperties以及@ConstructorBinding的时候,都可以使用构造函数赋值,都可以用到上面的两个@AllArgsConstructor、@RequiredArgsConstructor。
- 具体:只要记得,那些字段需要赋值,就把它列进构造方法的参数里面即可。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)