Spring中的@Configuration詳解
Spring中的@Configuration
Spring 提供了豐富的特性和功能,包括依賴注入、面向切面編程、事務(wù)管理、數(shù)據(jù)訪問、Web應(yīng)用程序開發(fā)等。
其中,@Configuration 是 Spring 中的一個注解,它用于標(biāo)記一個類為配置類,通過配置類可以定義和組裝 Spring Bean,并且支持高度靈活的配置方式。
在本文中,我們將深入探討 @Configuration 注解的底層原理,包括其與 Spring IoC 容器的集成、其對 Bean 的定義和裝配的實現(xiàn),以及其在 Spring 框架中的作用和用法。
@Configuration 注解的概述
@Configuration 注解是 Spring 3.0 版本引入的新特性,它用于將一個類標(biāo)記為配置類,通過配置類可以定義和組裝 Spring Bean。
配置類是一個普通的 Java 類,但是在類級別上添加了 @Configuration 注解,表明這個類用于配置 Spring Bean 的創(chuàng)建和管理。配置類可以包含多個用于定義 Bean 的方法,這些方法使用 @Bean 注解來標(biāo)記,并且返回一個對象,該對象會被 Spring IoC 容器管理。
配置類可以通過多種方式創(chuàng)建和組裝 Bean,包括使用其他配置類的 Bean、通過依賴注入注入其他 Bean、通過條件注解實現(xiàn) Bean 的條件化創(chuàng)建等。
配置類可以在 XML 配置文件、JavaConfig 類、注解等方式中進行定義,使得 Spring 的配置更加靈活和方便。
@Configuration 注解的主要作用有以下幾點:
- 定義 Bean:通過在配置類中使用 @Bean 注解,可以定義和組裝 Bean,并將其納入 Spring IoC 容器的管理,從而使得這些 Bean 可以在應(yīng)用程序中被使用。
- 管理依賴關(guān)系:配置類可以通過依賴注入的方式引入其他 Bean,從而實現(xiàn) Bean 之間的依賴關(guān)系管理。這樣,當(dāng)創(chuàng)建一個 Bean 時,其依賴的其他 Bean 會被自動注入,從而方便地管理 Bean 之間的依賴關(guān)系。
- 提供條件化配置:配置類可以通過條件注解實現(xiàn) Bean 的條件化創(chuàng)建,從而根據(jù)不同的條件創(chuàng)建不同的 Bean。這可以用于根據(jù)環(huán)境、配置等動態(tài)地選擇 Bean 的創(chuàng)建方式,使得配置更加靈活。
底層原理
@Configuration 注解的底層原理主要包括以下幾個方面的內(nèi)容:
- 與 Spring IoC 容器的集成
- Bean 的定義和裝配的實現(xiàn)
- 條件化配置的實現(xiàn)
- 配置類的加載和實例化過程
與 Spring IoC 容器的集成
@Configuration 注解與 Spring IoC 容器的集成是通過 ConfigurationClassPostProcessor 類來實現(xiàn)的。
ConfigurationClassPostProcessor 是一個 Bean 后置處理器,它負(fù)責(zé)處理標(biāo)記了 @Configuration 注解的配置類,并將其轉(zhuǎn)換為 Bean 定義并注冊到 Spring IoC 容器中。
ConfigurationClassPostProcessor 的處理過程分為三個階段:
- 解析階段:ConfigurationClassPostProcessor 會掃描配置類的類級別上的 @Configuration 注解,并解析其中的 Bean 定義和依賴關(guān)系,生成相應(yīng)的 BeanDefinition 對象。
- 注冊階段:ConfigurationClassPostProcessor 將解析得到的 BeanDefinition 對象注冊到 Spring IoC 容器中,成為真正的 Spring Bean。
- 驗證階段:ConfigurationClassPostProcessor 會驗證配置類中的 Bean 定義和依賴關(guān)系是否正確,如果有錯誤則會拋出異常。
通過 ConfigurationClassPostProcessor 的處理,@Configuration 注解標(biāo)記的配置類會被解析成真正的 BeanDefinition 對象,并注冊到 Spring IoC 容器中,從而使得這些配置類中定義的 Bean 可以被 Spring 容器管理和使用。
Bean 的定義和裝配的實現(xiàn)
@Configuration 注解標(biāo)記的配置類中,可以使用 @Bean 注解來定義 Bean,并將其納入 Spring IoC 容器的管理。@Bean 注解的底層實現(xiàn)主要通過 BeanMethod 類來實現(xiàn)。
BeanMethod 類是一個內(nèi)部類,它表示一個配置類中使用 @Bean 注解定義的方法。每個使用 @Bean 注解的方法都會被 BeanMethod 類表示,并包含相應(yīng)的 Bean 定義信息,例如 Bean 的名稱、類型、作用域、初始化方法、銷毀方法等。
- 在解析階段,ConfigurationClassPostProcessor 會掃描配置類中的 @Bean 注解,解析其中的 Bean 定義信息,并將其封裝成 BeanMethod 對象。在注冊階段,ConfigurationClassPostProcessor 會根據(jù) BeanMethod 對象創(chuàng)建相應(yīng)的 BeanDefinition 對象,并注冊到 Spring IoC 容器中。
- 在裝配階段,當(dāng)需要獲取一個使用 @Bean 注解定義的 Bean 時,Spring IoC 容器會通過調(diào)用相應(yīng)的 BeanMethod 對象的方法來創(chuàng)建 Bean 的實例。這樣,@Bean 注解的配置類中定義的 Bean 就可以被自動創(chuàng)建和裝配到其他 Bean 中,實現(xiàn)了依賴注入的功能。
條件化配置的實現(xiàn)
@Configuration 注解支持條件化配置,即根據(jù)不同的條件來判斷是否加載某個配置類或者創(chuàng)建某個 Bean。這個功能的底層實現(xiàn)主要依賴于 Condition 接口和 ConditionContext、AnnotatedTypeMetadata 兩個接口的實現(xiàn)。
- Condition 接口定義了一個 matches 方法,用于判斷是否滿足條件。當(dāng)某個配置類或者 Bean 使用了 @Conditional 注解,并傳入了一個實現(xiàn)了 Condition 接口的類時,Spring IoC 容器會在解析階段調(diào)用這個 Condition 類的 matches 方法來判斷是否滿足條件。如果滿足條件,那么這個配置類或者 Bean 就會被加載或者創(chuàng)建,否則就會被忽略。
- ConditionContext 和 AnnotatedTypeMetadata 接口分別用于在 Condition 接口的 matches 方法中獲取當(dāng)前的上下文信息和注解元數(shù)據(jù)。ConditionContext 提供了獲取 BeanFactory、Environment、ResourceLoader、ClassLoader 等信息的方法,可以用于判斷當(dāng)前環(huán)境的狀態(tài)。AnnotatedTypeMetadata 則提供了獲取配置類或者 Bean 的注解信息的方法,可以用于判斷注解的屬性值是否滿足條件。
通過這些接口的實現(xiàn),@Conditional 注解的配置類或者 Bean 可以根據(jù)不同的條件來進行動態(tài)加載或者創(chuàng)建,從而實現(xiàn)了條件化配置的功能。
配置類的加載和實例化過程
@Configuration 注解標(biāo)記的配置類在 Spring IoC 容器中的加載和實例化過程主要包括以下幾個步驟:
- 加載配置類:當(dāng) Spring IoC 容器啟動時,會掃描所有的配置類,并將其加載到容器中。這個過程是通過 ConfigurationClassParser 類來實現(xiàn)的。 ConfigurationClassParser 類負(fù)責(zé)解析配置類中的注解,包括 @Configuration、@Bean、@ComponentScan 等注解,并生成相應(yīng)的 BeanDefinition 對象。其中,@ComponentScan 注解用于指定需要掃描的包,從而找到其他的配置類和 Bean 定義。
- 解析 Bean 定義和依賴關(guān)系:在加載配置類的過程中,ConfigurationClassParser 會解析配置類中的 @Bean 注解,并生成相應(yīng)的 BeanDefinition 對象。同時,它還會解析配置類中的其他注解,例如 @Autowired、@Value 等注解,從而生成 Bean 之間的依賴關(guān)系。
- 注冊 Bean 定義:在解析完 Bean 定義和依賴關(guān)系后,ConfigurationClassParser 會將生成的 BeanDefinition 對象注冊到 Spring IoC 容器中。這個過程是通過調(diào)用 BeanDefinitionRegistry 接口的 registerBeanDefinition 方法來實現(xiàn)的。 實例化 Bean:當(dāng)需要獲取某個 Bean 時,Spring IoC 容器會根據(jù) Bean 的定義信息,實例化 Bean 并將其放入容器中。這個過程是通過調(diào)用 BeanFactory 接口的 getBean 方法來實現(xiàn)的。
在實例化 Bean 的過程中,Spring IoC 容器會先判斷 Bean 是否已經(jīng)存在于容器中。
- 如果存在,則直接返回已經(jīng)存在的 Bean 實例;
- 如果不存在,則會通過 Bean 的定義信息來創(chuàng)建新的 Bean 實例。
在創(chuàng)建 Bean 實例時,Spring IoC 容器會先檢查 Bean 的構(gòu)造函數(shù)是否有參數(shù)。
- 如果有參數(shù),則會按照參數(shù)類型或者參數(shù)名來從容器中獲取對應(yīng)的 Bean 實例,并傳入構(gòu)造函數(shù)中。
- 如果沒有參數(shù),則直接調(diào)用無參構(gòu)造函數(shù)來創(chuàng)建 Bean 實例。
創(chuàng)建 Bean 實例后,Spring IoC 容器會對 Bean 進行初始化,包括調(diào)用 Bean 的初始化方法(例如 @PostConstruct 注解標(biāo)記的方法)、應(yīng)用 Bean 的屬性值(例如 @Value 注解標(biāo)記的屬性)、處理 Bean 的生命周期回調(diào)(例如 InitializingBean 和 DisposableBean 接口的實現(xiàn))等。
最后,創(chuàng)建完成的 Bean 實例會被放入容器中,并可以通過 Bean 的名稱或者類型來進行訪問和使用。
總結(jié)
@Configuration 注解是 Spring 框架中用于標(biāo)記配置類的重要注解之一。
它允許我們通過 Java 類的方式來配置和管理 Bean 實例,從而實現(xiàn)了面向?qū)ο蟮呐渲梅绞健?/p>
@Configuration 注解的底層原理涉及到了代理對象、循環(huán)依賴解決方案、刷新機制、條件化配置等多個方面。
通過深入理解 @Configuration 注解的原理,我們可以更好地理解 Spring 框架中的配置方式,并在實際項目中靈活地應(yīng)用。
在使用 @Configuration 注解時,需要注意一些常見的使用原則,例如避免在配置類中使用 @Autowired 注解、避免循環(huán)依賴、合理使用條件化配置等。
同時,深入了解 @Configuration 注解的源碼實現(xiàn),對于排查和解決配置相關(guān)的問題也是非常有幫助的。
到此這篇關(guān)于Spring中的@Configuration詳解的文章就介紹到這了,更多相關(guān)Spring的@Configuration內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring mvc+localResizeIMG實現(xiàn)HTML5端圖片壓縮上傳
這篇文章主要為大家詳細(xì)介紹了使用spring mvc+localResizeIMG實現(xiàn)HTML5端圖片壓縮上傳,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04SpringBoot+Redis使用AOP防止重復(fù)提交的實現(xiàn)
本文主要介紹了SpringBoot+Redis使用AOP防止重復(fù)提交的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07mybatis那些約定的配置你真的都了解嗎(經(jīng)驗總結(jié))
mybatsi中Mapper和xml文件之間有很多約定俗稱的規(guī)則,比如名稱匹配,包掃描,別名等,這些規(guī)則是什么。如果想更加靈活,該如何配置呢?今天就給大家講一下如何配置mybatsi的xml文件2021-06-06Java實現(xiàn)byte[]轉(zhuǎn)List的示例代碼
byte,即字節(jié),由8位的二進制組成。在Java中,byte類型的數(shù)據(jù)是8位帶符號的二進制數(shù)。List?是一個接口,它繼承于Collection的接口。它代表著有序的隊列。本文將介紹如何通過java實現(xiàn)byte[]轉(zhuǎn)List,需要的可以參考一下2022-01-01springboot通過spel結(jié)合aop實現(xiàn)動態(tài)傳參的案例
SpEl 是Spring框架中的一個利器,Spring通過SpEl能在運行時構(gòu)建復(fù)雜表達(dá)式、存取對象屬性、對象方法調(diào)用等,今天通過本文給大家介紹springboot?spel結(jié)合aop實現(xiàn)動態(tài)傳參,需要的朋友可以參考下2022-07-07MyBatis使用annonation定義類型映射的簡易用法示例
這篇文章主要介紹了MyBatis使用annonation定義類型映射的簡易用法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-09-09Java抽象類和普通類區(qū)別、 數(shù)組跟List的區(qū)別解析
這篇文章主要介紹了Java抽象類和普通類區(qū)別、 數(shù)組跟List的區(qū)別,在這里需要注意List是一個接口,不能直接實例化,需要使用具體的實現(xiàn)類來創(chuàng)建對象,本文結(jié)合示例代碼介紹的非常詳細(xì),需要的朋友參考下吧2023-09-09MyBatis-Plus攔截器對敏感數(shù)據(jù)實現(xiàn)加密
做課程項目petstore時遇到需要加密屬性的問題,而MyBatis-Plus為開發(fā)者提供了攔截器的相關(guān)接口,本文主要介紹通過MyBatis-Plus的攔截器接口自定義一個攔截器類實現(xiàn)敏感數(shù)據(jù)如用戶密碼的加密功能,感興趣的可以了解一下2021-11-11