解讀@NoArgsConstructor,@AllArgsConstructor,@RequiredArgsConstructor的區(qū)別及在springboot常用地方
1. 先說結(jié)論
區(qū)別
- @NoArgsConstructor:生成無參的構(gòu)造方法。
- @AllArgsConstructor:生成該類下全部屬性的構(gòu)造方法。
- @RequiredArgsConstructor:生成該類下被final修飾或者non-null字段生成一個構(gòu)造方法。
場景
在springboot中,對于一個bean類,注入其他bean的時候,常見的是使用@Autowired,實際上也可以使用構(gòu)造函數(shù)注入,這個時候就可以使用@AllArgsConstructor或者@RequiredArgsConstructor來代替。
2. 代碼解析區(qū)別
@NoArgsConstructor 默認(rèn)都知道。
若不知道怎么查看java反編譯字節(jié)碼內(nèi)容,可以看一下:
Java如何進(jìn)行反編譯生成.java文件(javap、jad下載安裝使用)
1. @AllArgsConstructor
@AllArgsConstructor public class demo { private String name; // 被final修飾 private final String age; @NonNull private String sex; }
根據(jù)反編譯查看代碼:
public class demo { // 默認(rèn) 只要是該類下的字段,無論什么修飾,都會被參與構(gòu)造 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 { // 只構(gòu)造了有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
根據(jù)上面看反編譯代碼可以得出:只要是類里面字段,都會被加入到構(gòu)造函數(shù)里面,不管被什么修飾。
例子:
@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:只會構(gòu)造被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修飾。
注:強調(diào) 對需要的字段,為什么要強調(diào),請看下面的例子:
3. @RequiredArgsConstructor與@AllArgsConstructor在注入bean上區(qū)別
根據(jù)上面兩個例子,我們可以看出無論是那種方法都可以注入bean屬性對象,只是@RequiredArgsConstructor 是針對有條件的,沒有什么區(qū)別。
但如果是下面的需求呢:
在該類下,部分字段還需要使用@Value來注入值呢?
@Component @ToString public class ConstructorDemo { private BeanTest1 beanTest1; @NonNull private BeanTest2 beanTest2; private BeanTest3 beanTest3; @Value("${constructor.name:hello}") private String name; }
先思考一下:
一個bean如果使用構(gòu)造函數(shù)進(jìn)行bean屬性注入,那么當(dāng)然構(gòu)造函數(shù)不能加上name。
因為加上,在創(chuàng)建ConstructorDemo該bean的時候,需要找類型為String,名字是name的bean對象,當(dāng)然是不存在,必然會報錯。
因此,當(dāng)然不能使用@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. 總結(jié)
上面只是舉例了代替@Autowired的例子,實際上在json轉(zhuǎn)化為對象,以及在spring中從配置文件讀取配置使用@ConfigurationProperties以及@ConstructorBinding的時候,都可以使用構(gòu)造函數(shù)賦值,都可以用到上面的兩個@AllArgsConstructor、@RequiredArgsConstructor。
具體:只要記得,那些字段需要賦值,就把它列進(jìn)構(gòu)造方法的參數(shù)里面即可。
好了,以上僅為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
java中循環(huán)遍歷刪除List和Set集合中元素的方法(推薦)
下面小編就為大家?guī)硪黄猨ava中循環(huán)遍歷刪除List和Set集合中元素的方法(推薦)。小編覺得挺不錯的,在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12Spring?BeanDefinition父子關(guān)系示例解析
這篇文章主要為大家介紹了Spring?BeanDefinition父子關(guān)系示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08使用SpringBoot+Prometheus+Grafana實現(xiàn)可視化監(jiān)控
本文主要給大家介紹了如何使用Spring?actuator+監(jiān)控組件prometheus+數(shù)據(jù)可視化組件grafana來實現(xiàn)對Spring?Boot應(yīng)用的可視化監(jiān)控,文中有詳細(xì)的代碼供大家參考,具有一定的參考價值,需要的朋友可以參考下2024-02-02使用logback實現(xiàn)按自己的需求打印日志到自定義的文件里
這篇文章主要介紹了使用logback實現(xiàn)按自己的需求打印日志到自定義的文件里,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08Java并發(fā)編程之詳解CyclicBarrier線程同步
在之前的文章中已經(jīng)為大家介紹了java并發(fā)編程的工具:BlockingQueue接口,ArrayBlockingQueue,DelayQueue,LinkedBlockingQueue,PriorityBlockingQueue,SynchronousQueue,BlockingDeque接口,ConcurrentHashMap,CountDownLatch,本文為系列文章第十篇,需要的朋友可以參考下2021-06-06SpringMVC實現(xiàn)注解式權(quán)限驗證的實例
本篇文章主要介紹了SpringMVC實現(xiàn)注解式權(quán)限驗證的實例,可以使用Spring MVC中的action攔截器來實現(xiàn),具有一定的參考價值,有興趣的可以了解下。2017-02-02