@Autowired注解在抽象類中失效的原因及解決
@Autowired注解在抽象類中失效
最近在工作中遇到這個問題,在抽象類中使用Autowired這個注解,注入mybatis的dao時,總是出現(xiàn)空指針異常,通過日志的打印,發(fā)現(xiàn)是這個dao注入失敗為空。然后通過new出spring上下文對象,再去調(diào)用getBean()方法,獲取到這個注入的dao,這樣是可行的,但是總是覺得這不是最佳實踐,一定有比這個更加優(yōu)雅的方式能解決這個問題。
我們來還原一下這個問題:
1.定義一個抽象類
聲明為spring組件,在其中自動裝配另一個bean:
@Component
public abstract class BaseService {
@Autowired
Dao dao;
}
2.然后在他的子類中使用這個自動裝配的對象
@Component
public class myService extends BaseService{
public void print(){
//運行時為null
System.out.print(dao.toString());
}
}
在我們實例化子類對象的時候,抽象父類不能實例化,因為spring注入的是實例對象,而不是類,所以spring不會將dao自動裝配注入到一個實例中。但是我們通過在在抽象類中獲取的上下文對象中卻可以拿到dao,因為這個上下文對象
是我們自己手動new出來的,不是spring通過反射注入到對象中去的。因此這種方案是可行的。
下面介紹一種更優(yōu)雅的解決方案:
1.同樣是定義一個抽象類
public class BaseService {
Dao dao;
}
2.在子類中使用注解
@Component
public class myService extends BaseService{
//Autowired修飾方法時,根據(jù)方法參數(shù)類型判斷實例化哪個類
@Autowired
public void printDao(Dao dao){
super.dao = dao;//父類屬性注入
}
public void print(){
System.out.print(dao.toString());
}
}
這樣寫是不是要比我們直接去new applicationContext更加優(yōu)雅呢?
在抽象類中使用@Autowired
1.簡介
在本快速教程中,我們將說明如何在抽象類中使用 @Autowired 自動裝配注解。
我們將 @Autowired 應(yīng)用于 abstract 抽象類,并關(guān)注此時要考慮的重點。
2.Setter 方式注入
我們可以在設(shè)置方法上使用_@Autowired_:
public abstract class BallService {
private LogRepository logRepository;
@Autowired
public final void setLogRepository(LogRepository logRepository) {
this.logRepository = logRepository;
}
}
當(dāng)我們使用_@Autowired_上setter方法,我們應(yīng)該用final 關(guān)鍵字,這樣子類便不能覆蓋setter方法。否則,注解將無法正常運行。
3.構(gòu)造函數(shù)注入
我們不能在抽象類的構(gòu)造函數(shù)上使用_@Autowired_。
Spring 不會在抽象類的構(gòu)造函數(shù)上解析 @Autowired 注解。子類應(yīng)為 super 構(gòu)造函數(shù)提供必要的參數(shù)。
相反,我們應(yīng)該在子類的構(gòu)造函數(shù)上使用_@Autowired_:
public abstract class BallService {
private RuleRepository ruleRepository;
public BallService(RuleRepository ruleRepository) {
this.ruleRepository = ruleRepository;
}
}
@Component
public class BasketballService extends BallService {
@Autowired
public BasketballService(RuleRepository ruleRepository) {
super(ruleRepository);
}
}
4.備忘單
讓我們總結(jié)一些要記住的規(guī)則。
首先,抽象類不會進(jìn)行組件掃描,因為沒有具體的子類就無法實例化。
其次,在抽象類中可以進(jìn)行setter注入,但是如果不對setter方法使用_final_關(guān)鍵字,因而存在一定誤用的風(fēng)險。如果子類覆蓋 setter 方法,則應(yīng)用程序可能不能正常運行。
第三,由于 Spring 在抽象類中不支持構(gòu)造函數(shù)注入,因此通常應(yīng)該讓具體的子類提供構(gòu)造函數(shù)參數(shù)。這意味著我們需要在具體子類中依賴構(gòu)造函數(shù)注入。
最后,將構(gòu)造函數(shù)注入用于必需的依賴項,并將setter注入用于可選的依賴項是一個很好的經(jīng)驗法則。但是,正如我們可以從抽象類的一些細(xì)微差別中看到的那樣,通常在這里構(gòu)造函數(shù)注入更為有利。
因此,實際上我們可以說具體的子類控制著它的抽象父類如何獲得其依賴項。 Spring 在裝配子類時, 會對其依賴進(jìn)行注入。
5.結(jié)論
在本文中,我們練習(xí)了在抽象類中使用_@Autowired_,并解釋了一些關(guān)鍵點。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java中@ConfigurationProperties實現(xiàn)自定義配置綁定問題分析
這篇文章主要介紹了@ConfigurationProperties實現(xiàn)自定義配置綁定問題,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08
你肯定能看懂的Java IO相關(guān)知識總結(jié)
群里有大佬說想讓我寫一篇NIO,一直也沒寫,但是和同事聊天也說對Java的IO不是很清晰,因此今天就寫下Java的io,先打個基礎(chǔ),下次寫NIO,需要的朋友可以參考下2021-05-05
Java關(guān)于List集合去重方案詳細(xì)介紹
實際項目開發(fā)中,很多業(yè)務(wù)場景下都會遇見集合去重。在說到List集合去重之前,首先我們回顧下普通類型的list如何去重2021-09-09
Java?Mybatis使用resultMap時,屬性賦值順序錯誤的巨坑
這篇文章主要介紹了Java?Mybatis使用resultMap時,屬性賦值順序錯誤的巨坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01

