實體類使用@Builder,導致@ConfigurationProperties注入屬性失敗問題
1. 前言
這里只是列出,可能需要補一下的知識點:
具體的yml文件字符串、List、Map的書寫方式并使用@ConfigurationProperties注入配置類.
使用@Builder導致的無法創(chuàng)建無參構造方法
2. 場景
@ConfigurationProperties注入屬性,有兩個很重要的條件:
- 該類必須是bean對象,即加了@Component注解。
- 該類必須得有set方法,即加@Setter注解。
偶然一次發(fā)現(xiàn),當在該類加上@Builder注解,會直接導致無法屬性注入。
重現(xiàn):
正常情況下:
@ToString
@Setter
@Component
@ConfigurationProperties(prefix = "failed.test")
public class demoFailedTest {
private String username;
private int age;
private demoPerson demoPerson;
}
@Setter
@ToString
public class demoPerson {
private String name;
private String sex;
}
@Component("demoFailedTestRunner")
public class demoRunner implements ApplicationRunner {
@Autowired
demoFailedTest demoFailedTest;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(demoFailedTest);
}
}
failed:
test:
user-name: failedTest
age: 19
demo-person:
name: person
sex: boy

異常情況:當在demoPerson類上加上@Builder注解:
@Builder
@Setter
@ToString
public class demoPerson {
private String name;
private String sex;
}

一開始都驚了,本來就是符合條件的,demoPerson類上面有set方法,不應該注入不進來。
3. 解釋
1.上面兩張圖片有個輸出有個很細微的差異,一開始我也沒有看出來,后來才反應過來了:
第一個:
demoFailedTest(username=failedTest, age=19, demoPerson=demoPerson(name=person, sex=boy))
第二個:
demoFailedTest(username=failedTest, age=19, demoPerson=null)
注: demoPerson類上 加了@ToString
講道理,第二個報錯不應該是:
demoFailedTest(username=failedTest, age=19, demoPerson=demoPerson(name=null, sex=null))
這樣子才是真正注入不進來屬性的結果。
那么現(xiàn)在直接 demoPerson=null 代表 該demoPerson根本沒有被創(chuàng)建對象?。?!
2.后來詳細去了解了@Builder注解的作用:
詳細:使用@Builder導致的無法創(chuàng)建無參構造方法
簡單說一下:就是如果你只是使用了@Builder則會導致 該類的沒有無參構造函數(shù),會有全參構造函數(shù)。
3.重點:spring屬性注入的時候,為什么要有set方法,顯示它是使用set方法注入的,它又不能直接使用對象.set方法(),想必是使用了反射,那就必須得有對象吧,可得 spring肯定是先反射創(chuàng)建對象,是的,沒錯,spring默認是使用無參構造函數(shù)創(chuàng)建對象,再調(diào)用反射的set方法。
4.因此,如果加上@Builder注解,會沒有無參構造函數(shù)方法,當然是沒有辦法創(chuàng)建對象了,因此才會出現(xiàn) demoPerson=null的結果。
4. 解決方法
具體@Builder的解決方法,上面鏈接里面有三種,我演示其中一種,即在該類上加上@AllArgsConstructor@NoArgsConstructor。
@ToString
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class demoPerson {
private String name;
private String sex;
}

5. 思考
根據(jù)第四大點的解決方法,加上@AllArgsConstructor、@NoArgsConstructor即可,但有沒有想過為什么要用@Builder方法,
原因:
- builder創(chuàng)建對象方式很優(yōu)雅,寫的很簡潔。
- 有沒有一種可能,就是需求就是不想對外提供默認無參構造方法,或者全參構造方法,不想別人隨便就可以new 對象出來了。
如果要滿足第二點原因,顯然現(xiàn)在是無法做到的,因為spring使用set方法注入,得有無參構造方法先創(chuàng)建對象,但是我們又不想提供無參構造方法,這不是矛盾嗎?
再額外補充一個問題:如果這個Person類,我只想通過配置文件注入之后,永遠不被修改,固然不能提供set方法,但是因為spring使用set方法注入屬性,這不也是矛盾嗎?
此時,突然腦子里面肯定會出現(xiàn)一個想法:為什么只會有set方法注入,不應該吧,set都可以,應該也可以有構造函數(shù)注入吧。
是的,下一篇文章:
spring的構造函數(shù)注入屬性@ConstructorBinding
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
使用JAVA獲取nacos配置信息出現(xiàn)null,獲取不到的解決
文章討論了在使用Java獲取Nacos配置信息時遇到的問題,特別是調(diào)用ConfigService獲取配置時出現(xiàn)null的情況,作者嘗試了多種解決方法,最終發(fā)現(xiàn)更換jar包版本(1.*)解決了問題,作者分享了個人經(jīng)驗,希望能對大家有所幫助2025-12-12
RestTemplate報錯400 Bad Request的解決方案
在使用Spring Boot時,若直接通過@Autowired注入RestTemplate可能會遇到400BadRequest錯誤,原因在于Spring Boot官方文檔指出,由于RestTemplate實例通常需要在使用前進行定制,因此Spring Boot不會自動配置單個RestTemplate Bean2024-11-11
SpringBoot創(chuàng)建多模塊項目的全過程記錄
這篇文章主要給大家介紹了關于SpringBoot創(chuàng)建多模塊項目的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01

