12.16 踩坑了!使用 @Autowired 注入成功,GetBean 方法卻獲取不到



踩坑了?!

之前講過 當@Transactional遇到@CacheEvict,你的代碼是不是有bug! 現在要在事務提交之後清除緩存。在Spring4.2 之後,可以使用@TransactionalEventListener選擇在事務提交之後再消費對應的事件。

踩坑了!使用 @Autowired 注入成功,GetBean 方法卻獲取不到

為了方便發送事件,偷懶使用了靜態方法:

踩坑了!使用 @Autowired 注入成功,GetBean 方法卻獲取不到

其中,SpringUtil.getBean()方法的內部實現為:

踩坑了!使用 @Autowired 注入成功,GetBean 方法卻獲取不到

滿心歡喜寫完代碼,一運行,直接報錯,報錯信息為 IoC 容器中不存在ApplicationEventPublisher。

怎麼解決?解決的方案也很簡單:使用@Autowired注入ApplicationEventPublisher,調用其publishEvent方法。

深入思考

可是,為什麼ApplicationEventPublisher可以通過@Autowired進行注入,卻不能使用BeanFactory#getBean方法來獲取呢?

畫外音:千萬不要只限於解決問題,多思考,知其然並知其所以然。

看過 Spring 源碼的小夥伴不知道還記不記得,在refresh()方法中,會調用prepareBeanFactory,在該方法中,註冊了可解析依賴項。

踩坑了!使用 @Autowired 注入成功,GetBean 方法卻獲取不到

從源碼中可以知道,一些特殊實例對象是存放在DefaultListableBeanFactory#resolvableDependencies變量中的,在容器啟動時,如果發現需要注入這些特定的實例對象,就直接在該變量中獲取,自然也就不能通過BeanFactory#getBean方法來獲取了。

DEMO

寫個 demo 程序來嘗試使用一下resolvableDependencies。

踩坑了!使用 @Autowired 注入成功,GetBean 方法卻獲取不到

測試結果和ApplicationEventPublisher一樣,可以在 Bean 中通過@Autowired的方式來注入MySpecificBean,但卻無法通過BeanFactory#getBean方法來獲取。

踩坑了!使用 @Autowired 注入成功,GetBean 方法卻獲取不到

寫在最後

很多人都說要看源碼,但是看源碼的目的是什麼?看源碼,不是為了面試吹牛,也不是為了重複造輪子。看源碼是為了深入瞭解這個框架的底層原理,為了以後遇到問題不會懵,可以解決百度無法解決的問題。我們可以學習優秀源碼的設計思想,學習如何取一個好的類名、好的方法名,如何使用設計模式等等。


作者:程序員小黑
原文鏈接:https://juejin.im/post/5df6d6746fb9a0162c486cec


分享到:


相關文章: