Spring自動注入失敗的解決方法
Spring自動注入失敗如何解決?
我有一個被Spring @Service注解的類(MileageFeeCalculator),它有一個用@Autowired注入的變量(rateService),但是當我用這個變量的時候,它顯示為null。日志顯示MileageFeeCalculator bean和MileageRateService bean都被創(chuàng)建了,但是當我調(diào)用service上的mileageCharge ()方法時,就會報NullPointerException錯誤。為什么Spring不能自動注入這個實例?
Controller:
@Controller public class MileageFeeController { @RequestMapping("/mileage/{miles}") @ResponseBody public float mileageFee(@PathVariable int miles) { MileageFeeCalculator calc = new MileageFeeCalculator(); return calc.mileageCharge(miles); } }
Service:
@Service public class MileageFeeCalculator { @Autowired private MileageRateService rateService; // <--- should be autowired, is null public float mileageCharge(final int miles) { return (miles * rateService.ratePerMile()); // <--- throws NPE } }
本應被注入Service但是并沒有的類
@Service public class MileageRateService { public float ratePerMile() { return 0.565f; } }
為什么我調(diào)用GET /mileage/3這個請求的時候,會報這樣的錯誤:
java.lang.NullPointerException: null at com.chrylis.example.spring_autowired_npe.MileageFeeCalculator.mileageCharge(MileageFeeCalculator.java:13) at com.chrylis.example.spring_autowired_npe.MileageFeeController.mileageFee(MileageFeeController.java:14) ...
回答
@Autowired注解的字段為null是因為,Spring無法獲取你用new關鍵字創(chuàng)建的類,也無法自動注入它。
Spring Ioc容器有三個主要的邏輯組件:應用程序可以使用的注冊表(ApplicationContext);通過把依賴項與上下文中的bean匹配,將依賴的對象注入的配置器系統(tǒng);以及一個依賴解析器,它可以查看許多不同bean的配置,并確定如何按必要的順序?qū)嵗团渲盟鼈儭?/p>
Ioc容器并沒有魔法,除非你以某種方式通知它,否則它無法獲取Java對象。當你調(diào)用new創(chuàng)建對象時,JVM實例化新對象,并將其中一個副本交給你——它并不經(jīng)歷Spring的配置過程。有三種方法可以配置bean實例。
注入你的bean
最好的選擇是讓Spring注入所有的bean;這樣的代碼量會最少并且也最容易維護。為了使注入如你所愿,需要把MileageFeeCalculator像這樣注入。
@Controller public class MileageFeeController { @Autowired private MileageFeeCalculator calc; @RequestMapping("/mileage/{miles}") @ResponseBody public float mileageFee(@PathVariable int miles) { return calc.mileageCharge(miles); } }
如果你需要為不同的請求都創(chuàng)建一個類的新實例,可以通過Spring注解的scopes實現(xiàn)。
使用@Configurable
如果你真的需要把new出來的對象保存進行注入,那可以使用Spring的@Configurable注解,通過使用AOP在編譯時織入你的對象中。這種方法將代碼插入到對象的構(gòu)造函數(shù)中,提醒Spring這個對象正在被創(chuàng)建,這樣Spring就能夠配置新實例了。這需要你添加一些配置信息。并打開Spring的運行時配置處理器。Roo Active Record系統(tǒng)使用這種方法來允許實體的new實例獲取注入的必要持久性信息。
@Service @Configurable public class MileageFeeCalculator { @Autowired private MileageRateService rateService; public float mileageCharge(final int miles) { return (miles * rateService.ratePerMile()); } }
手動查找bean:不推薦
這種方法只適用于在特殊情況下與遺留代碼對接。創(chuàng)建一個Spring可以自動注入并且遺留代碼也能調(diào)用的單例適配器總是可取的,但是也許可以直接向spring application context請求bean實例。
為了做到這點,你需要一個類,該類提供了對ApplicationContext對象的引用
@Component public class ApplicationContextHolder implements ApplicationContextAware { private static ApplicationContext context; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { context = applicationContext; } public static ApplicationContext getContext() { return context; } }
之后你的遺留代碼就可以調(diào)用getContext()方法獲取所需的bean實例了。
@Controller public class MileageFeeController { @RequestMapping("/mileage/{miles}") @ResponseBody public float mileageFee(@PathVariable int miles) { MileageFeeCalculator calc = ApplicationContextHolder.getContext().getBean(MileageFeeCalculator.class); return calc.mileageCharge(miles); } }
以上就是Spring自動注入失敗的解決方法的詳細內(nèi)容,更多關于Spring自動注入失敗的解決的資料請關注腳本之家其它相關文章!
相關文章
SpringBoot整合Swagger Api自動生成文檔的實現(xiàn)
本文主要介紹了SpringBoot整合Swagger Api自動生成文檔的實,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-06-06Linux中Java開發(fā)常用軟件安裝方法總結(jié)
這篇文章主要介紹了Linux中Java開發(fā)常用軟件安裝方法總結(jié),需要的朋友可以參考下2020-02-02springcloud項目里application.yml不加載的坑及解決
這篇文章主要介紹了springcloud項目里application.yml不加載的坑及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07