品Spring:負責bean定義註冊的兩個“排頭兵”

来源:https://www.cnblogs.com/lixinjie/archive/2019/09/28/taste-spring-007.html
-Advertisement-
Play Games

別看Spring現在玩的這麼花,其實它的“籌碼”就兩個,“容器”和“bean定義”。只有先把bean定義註冊到容器里,後續的一切可能才有可能成為可能。所以在進階的路上如果要想走的順暢些,徹底搞清楚bean定義註冊的所有細節至關重要。畢竟這是萬里長征的第一步。有句話怎麼說來著,“勿在浮沙築高臺”。Sp ...


別看Spring現在玩的這麼花,其實它的“籌碼”就兩個,“容器”和“bean定義”。

只有先把bean定義註冊到容器里,後續的一切可能才有可能成為可能。

所以在進階的路上如果要想走的順暢些,徹底搞清楚bean定義註冊的所有細節至關重要。

畢竟這是萬里長征的第一步。有句話怎麼說來著,“勿在浮沙築高臺”。


Spring步入註解和Java配置的時代也有些時日了。而且也旗幟鮮明的表達了bean的註冊方法。

這不,就是這個介面,AnnotationConfigRegistry,如下圖01:


再來看下這個介面的名字,有三個單片語成,AnnotationConfigRegistry

第一個表示註解,第二個表示Java配置,第三個表示註冊。

合起來的意思可以理解為,基於註解和Java配置的bean定義註冊當然,這是我猜的,哈哈哈。

這是一個很牛X的介面,理由見下圖02:

 

納尼,所有的容器類都實現了它

不管是web的、非web的,傳統Spring的、SpringBoot的,響應式的、Servlet的。

簡直是老少通吃、婦孺皆宜啊。淡定、淡定。

這個介面的兩個方法非常簡約

一個是直接把一個類(Class<?>)進行註冊。

一個是通過掃描指定的包(Package)里的類進行註冊。

請註意我剛剛使用了“簡約”而沒有使用“簡單”,因為簡約往往並不等於簡單,反而更多時候等於難。


講了這麼多,終於可以讓今天的主角登場了,來來來,掌聲響起來。

就是這兩個類:

AnnotatedBeanDefinitionReader

ClassPathBeanDefinitionScanner

第一個類就是站在介面第一個方法register背後默默付出的。

第二個類就是負責搞定介面第二個方法scan後面所有事情的。

下麵開始進行具體的講解,只需要知道都幹了什麼即可,至於怎麼乾的,不需要瞭解。

看第一個類,如下圖03:

 

第一個欄位類型是BeanDefinitionRegistry,這是容器(或bean factory)會實現的介面。

用於把一個BeanDefinition(bean定義)註冊到容器中,看下它的這個方法,如下圖04:

 

編程新說註:對“bean定義”這個概念不清楚的,可以在文末查看本系列《品Spring》文章的頭幾篇。

剛剛應該看到在註冊bean定義時需要一個bean名稱(即beanName),因此該第二個欄位發揮作用了。

它就是BeanNameGenerator。例如,有一個類是UserController,它上面標了註解@Controller("user")。

首先它會把註解的value屬性作為名稱,此時就是user啦。

如果沒有指定value屬性,就像這樣@Controller,此時就是類的短名稱且首字母小寫,即userController。

這就是bean名稱的生成策略,在實際開發中不就是這樣的嘛。

第三個欄位是ScopeMetadataResolver,是來決定bean實例的範圍(即生命周期)的。

常見的生命周期有四種,PROTOTYPE(原型)、SINGLETON(單例)、REQUEST(請求)、SESSION(會話)。

就是通過檢查類上有沒有@Scope這個註解。如果有的話,就按指定的走,沒有的話,就按單例走。

第四個欄位是ConditionEvaluator,條件計算器,根據“條件”判斷一個bean定義該不該被註冊。

這可是SpringBoot自動配置(AutoConfiguration)的基石啊。

就是去檢測類上有沒有標@Conditional這個註解。如果沒有的話,bean定義會被註冊。

如果有的話,需要再去計算具體的“條件”,然後才能確定bean定義到底要不要註冊。

哎呀,註冊一個bean定義好麻煩啊,喘口氣,繼續吧。嘿嘿。


下麵開始真正進入註冊的方法,先看下方法的參數吧,如下圖05:

 

 

方法共有5個參數,只有第一個是必須的,後面的都可以為空。

第一個參數,annotatedClass,是Class<?>,表示要被註冊的類。

第二個參數,instanceSupplier,是一個函數式介面,Supplier<T>,可以提供這個bean的實例對象,這樣就不再需要通過反射調用構造函數了。

第三個參數,name,bean名稱,如果傳的話就不用再生成了。

第四個參數,qualifiers,是一組用作限定修飾符的註解,Class<? extends Annotation>[]。

第五個參數,definitionCustomizers,是一組可以自定義bean定義的介面,BeanDefinitionCustomizer。

整個處理過程分為九步,如下圖06:

 

第一步,先把類轉變為bean定義,即把Class<?>轉變為BeanDefinition。具體是AnnotatedGenericBeanDefinition這個類。

第二步,使用條件計算器來確定是否要註冊這個bean定義。

第三步,確定這個bean的生命周期。

第四步,確定這個bean的名稱。

第五步,處理定義的公共註解信息。如下圖07:

 

就是@Lazy@Primary@DependsOn@Role@Description這五個註解。

從類上分別獲取這些註解,然後從註解中讀出需要的信息,再把這些信息設置到bean定義中。

第六步,處理限定修飾符,就是@Primary@Lazy@Qualifier這三個註解。

這個幾個註解是從方法參數傳入的,上一步的註解是從類上讀取的,它們不重覆也不衝突。

編程新說註:這些註解的含義和用法,這裡就不說了,畢竟這是“追求深度”的文章。

第七步,應用bean定義自定義器,對bean定義進行一些自定義。

第八步,根據bean的生命周期,使用AOP技術為該bean定義生成代理。

第九步,把這個bean定義註冊到容器中。

這就是一個bean定義的完整註冊過程。媽呀,讓我歇會兒。

編程新說註:第二個類註冊bean定義的整體邏輯和第一個類完全一樣。只是獲取bean定義的方式不同。

下麵看第二個

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 簡單工廠模式 概念 簡單工廠模式屬於創建型模式,又叫做靜態工廠方法(Static Factory Method)。簡單工廠模式是由一個工廠對象決定創建哪一種產品類實例。在簡單工廠模式中,可以根據參數的不同返回不同類的實例。簡單工廠模式專門定義一個類來負責創建其他類的實例,被創建的實例通常都具有共同的 ...
  • 一、設計模式(Design Pattern): 1.設計模式的概念 是前輩們對代碼開發經驗的總結,是解決特定問題的一系列套路。它不是語法規定,而是一套用來提高代碼可復用性、可維護性、可讀性、穩健性以及安全性的解決方案。使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 2.學習設 ...
  • 外觀模式(Facade): 外部通過一個統一的介面,訪問子系統中的一群介面。外觀模式定義了一個高層介面,為子系統中的一組介面提供一個一致的入口,使得子系統更容易使用。外觀模式相對比較簡單,可以理解為中介,原先租房需要自己一個個篩選,聯繫房東,談好價格,簽合同等等,現在不需要這些了,只要你說出要求中介 ...
  • 場景 不知道大家有沒有遇到這樣的情況,就是去自動取款機取錢的時候,比如說你去取1000塊錢,這個時候系統會先幫你把1000塊錢扣除,然後自動取款機再把錢吐出來。但是如果取款機出現問題,會發現錢被扣了,但是錢沒有取出來。我第一次遇到這個問題的時候很擔心,當時跨行取取了3000塊錢,簡訊提醒我錢已經被扣 ...
  • 此文前端框架使用 "rax" ,全篇代碼暫未開源(待開源) 原文鏈接地址: "Nealyang/PersonalBlog" 前言 貌似在面試中,你如果設計一個 react/vue 組件,貌似已經是司空見慣的問題了。本文不是理論片,更多的是自己的一步步思考和實踐。文中會有很多筆者的思考過程,歡迎評論區 ...
  • 前言 今天我們一起來看行為型設計模式中的命令模式、何為命令模式呢?先談命令——我現在需要對某一條信息進行刪除,我進行點擊刪除按鈕。後臺執行刪除的命令、對信息進行刪除。那麼我們要講的命令模式又是什麼呢?命令模式就是把一個操作或者行為抽象為一個對象。然後通過對命令的抽象化來使得發出命令的職責和執行命令的 ...
  • 概述 簡單介紹一下七大設計原則: 1. 開閉原則 :是所有面向對象設計的核心,對擴展開放,對修改關閉 2. 依賴倒置原則 :針對介面編程,依賴於抽象而不依賴於具體 3. 單一職責原則 :一個介面只負責一件事情,只能有一個原因導致類變化 4. 介面隔離原則 :使用多個專門的介面,而不是使用一個總介面 ...
  • 一 鎖 行級鎖 select_for_update(nowait=False, skip_locked=False) 註意必須用在事務裡面,至於如何開啟事務,我們看下麵的事務一節。 返回一個鎖住行直到事務結束的查詢集,如果資料庫支持,它將生成一個 SELECT ... FOR UPDATE 語句。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...