答讀者問:BeanFactoryPostProcessor 似乎失效了?
來源:江南一點雨
有小夥伴在學習 Spring 原始碼影片的時候,看了松哥講的 BeanFactoryPostProcessor 的用法之後,提出了這樣一個問題:
我來跟大家補充一下這個問題的上下文:
我講了 BeanFactoryPostProcessor,分析了其原理,也講了具體的使用場景,一個典型的使用場景是我們在 XML 中定義 Bean 的時候,如果 Bean 的屬性是使用了 properties 檔案佔位符如 ${db.username}
這種,那麼在 BeanFactoryPostProcessor 階段,就會對這個佔位符進行處理,將其替換成真正的 value。然後我還順手給大家舉了一個例子,我在 XML 檔案中定義 Bean 的時候,給 Bean 的某一個屬性設定 value 為 ^username,然後在 BeanFactoryPostProcessor 中,我將 ^username 改為某一個字串。
小夥伴看了松哥講的內容之後,也照著寫了一個,就是上面圖片中的程式碼,不同的是,他是將 XML 配置改為了 Java 程式碼配置,結果發現屬性 hok
並未變為 NB
,因此有了上述問題。
我覺得這個問題問的很好,給了小夥伴們一個從其他方面理解 Spring 的機會,這也是我前面一直強調的,這次的 Spring 影片需要各位小夥伴一起發力,大家有關於 Spring 的任何問題都可以提,我負責透過原始碼來回答你。
問題分析
這個問題的分析,得先從 BeanDefinition 開始。在講 BeanFactoryPostProcessor 之前,松哥已經和小夥伴們分析過 BeanDefinition 了,無論我們是透過 Java 程式碼還是透過 XML 檔案定義的 Bean 物件,在解析稱為 Bean 物件之前,得先解析成為 BeanDefinition,BeanDefinition 則有不同的分類,對於 XML 檔案定義的 Bean,最終解析為 GenericBeanDefinition,而透過 @Bean 註解定義的 Bean 則解析為 ConfigurationClassBeanDefinition。
但是這兩個的處理原理顯然是有差異的。
對於 XML 定義的 Bean 來說,很明顯 XML 中的所有屬性都要先解析到 BeanDefinition 中,包括我們在 XML 中配置的 Bean 的各種屬性,這一步是在 Spring 容器 refresh 方法中構建 BeanFactory 的時候完成的(obtainFreshBeanFactory 方法),這一步完成之後,在後面的步驟會去執行容器中所有的 BeanFactoryPostProcessor(invokeBeanFactoryPostProcessors),此時就會把前面解析出來的 BeanDefinition 中帶有佔位符的屬性給替換過來,最後在 refresh 方法中執行 finishBeanFactoryInitialization 方法完成 Bean 的初始化。
按照上面這一套流程順序,佔位符被解析成為正常字串沒什麼問題。
但是,如果是 @Bean 註解配置的 Bean,則會有所差異。
首先,@Bean 註解所標記的方法要被解析為一個 ConfigurationClassBeanDefinition,這個過程本身是透過 ConfigurationClassPostProcessor 來完成的,而 ConfigurationClassPostProcessor 本質上其實就是一個 BeanFactoryPostProcessor,換言之,@Bean 註解標記的方法是在 BeanFactoryPostProcessor 中被解析為 ConfigurationClassBeanDefinition 的。ConfigurationClassBeanDefinition 這個 BeanDefinition 主要用來記錄 @Bean 註解所標記的方法所屬的物件、方法的名稱、方法物件、方法引數、註解的引數等等資訊,把這些資訊記錄下來,將來在初始化 Bean 的時候,透過反射執行目標方法就可以了,即方法裡邊的內容是什麼,ConfigurationClassBeanDefinition 其實並不關心。
最後則是和 XML 一樣,在 finishBeanFactoryInitialization 方法中完成 Bean 的初始化。
經過上面分析,小夥伴們可以看到,透過 @Bean 註解定義的 Bean,我們為屬性賦值是在方法內部完成的,這些方法內部的邏輯其實並未被解析到 BeanDefinition 中,顯然也沒有必要把方法內部的邏輯解析到 BeanDefinition 上去,因此,透過 @Bean 註解定義的 Bean,如果屬性中使用了佔位符,是無法透過 BeanFactoryPostProcessor 自動解析的。
好啦,現在小夥伴提出的問題大傢伙都明白了吧?
以上的分析中,方法的具體邏輯在 Spring 原始碼中都有詳細講解,所以這裡我只是和大家梳理了思路,具體實現小夥伴可以參考我們的原始碼影片。
歡迎各位小夥伴在學習過程中繼續提出高質量問題,一起把這套 Spring 原始碼教程做紮實了。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024922/viewspace-2993493/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 冴羽答讀者問:30 歲了, 現在開始努力,晚嗎?
- 答讀者問:關於隱式 id 重複的問題
- 冴羽答讀者問:悄悄過來蹭個回答
- 冴羽答讀者問:怎麼才能不焦慮?
- 冴羽答讀者問:怎麼平衡工作與生活?
- 冴羽答讀者問:啦啦啦啦啦啦
- 冴羽答讀者問:冴羽哥哥 額愛你
- 冴羽答讀者問:人生的意義是什麼?
- 冴羽答讀者問:錢和成長,哪個更重要?
- 冴羽答讀者問:何時能夠像你一樣優秀?
- 冴羽答讀者問:怎麼才能像你一樣長到180?
- 冴羽答讀者問:怎麼才能像你一樣寫文章如喝水?
- 冴羽答讀者問:人生低谷時,如何快速調整、重回正軌?
- 冴羽答讀者問:你是怎麼理解知行合一的?
- 【答書友問之十七】一年讀了十六本書是不是太少?
- 冴羽答讀者問:如何學習更有計劃性、提升更穩更快?
- 冴羽答讀者問:如何快速找到一個聊得來的人生伴侶
- Spring原始碼解讀之BeanFactoryPostProcessor的處理Spring原始碼Bean
- 冴羽答讀者問:功利性學習的心態,你是否也會有?
- 冴羽答讀者問:如何在工作中打造影響力,帶動同事?
- 問答營銷的流程和特點——以使用者思維做問答營銷
- MySQL 實戰 | 08 懵逼,可重複讀好像失效了?MySql
- 基於CNN的閱讀理解式問答模型:DGCNNCNN模型GC
- 開發者問第四期問答分享來啦!
- 開發者問第一期問答分享來啦
- 答讀者疑問:為什麼我的 manifest.json 檔案無法正確被載入試讀版JSON
- css失效問題CSS
- 社群問答精選|ChatGPT for SegmentFault 十問十答ChatGPT
- 問了幾人,MySQL changebuffer 這點都沒答對MySql
- 冴羽答讀者問:如果有機會,你會選擇脫產學習深造嗎?
- 答讀者問(1):非模式物種找marker;如何根據marker定義細胞型別模式型別
- 提問與問答技巧
- 基礎問答
- 問答專案
- Redis叢集高頻問答,連夜肝出來了Redis
- kubernetesgraceperiod失效問題排查
- MyBatis order by失效問題MyBatis
- @Value失效的問題