SpringBoot注解生效原理全解析
Spring Boot 注解生效原理分析
Spring Boot 的注解**(如 @RestController、@Service、@Autowired、@Configuration 等)在開(kāi)發(fā)中使用非常廣泛,但它們為什么能“自動(dòng)生效”?**本文將深入解析其背后的原理。
Spring 注解的生效依賴于 Spring 容器(ApplicationContext) 和 注解處理器(BeanPostProcessor / ConfigurationClassPostProcessor 等)。
前置:Bean 的聲明與注冊(cè)
@Component、@Service、@Controller、@Repository 等注解,都是用于標(biāo)記一個(gè)類為 Spring 管理的 Bean。
生效機(jī)制
1、 @Configuration 、 @Component、@ComponentScan 生效原因如下:
Spring 在啟動(dòng)時(shí),進(jìn)行上下文刷新refreshContex()然后觸發(fā)ConfigurationClassPostProcessor掃描所有 @Configuration 、 @Component等類注冊(cè)成BeanDefination, @ComponentScan 觸發(fā)包掃描,找到其他 @Component/@Service/@Controller將其也注冊(cè)成 BeanDefination。
2、自動(dòng)注入 @Autowired 實(shí)現(xiàn)機(jī)制:
@Autowired 的生效依賴:依賴注入(DI)機(jī)制 和 后置處理器(BeanPostProcessor)。
關(guān)鍵類:
AutowiredAnnotationBeanPostProcessor 處理 @Autowired 注解。
處理流程:
- AutowiredAnnotationBeanPostProcessor負(fù)責(zé)掃描所有 Bean 中的 @Autowired 注解,決定注入哪一個(gè) Bean。
- DependencyDescriptor描述依賴關(guān)系,包括類型、是否必需、泛型等。
- BeanFactory提供 Bean 實(shí)例,用于實(shí)際注入。
1. 啟動(dòng)入口
SpringApplication.run(App.class, args)
→ 創(chuàng)建ApplicationContext(通常是AnnotationConfigServletWebServerApplicationContext)
→ 調(diào)用refresh()(IOC 容器的核心刷新過(guò)程)。
2.refresh()關(guān)鍵步驟
在 AbstractApplicationContext#refresh() 中有一行核心邏輯:
invokeBeanFactoryPostProcessors(beanFactory);
這里會(huì)執(zhí)行所有 BeanFactoryPostProcessor,其中最重要的是:
?? ConfigurationClassPostProcessor
3.ConfigurationClassPostProcessor的作用
源碼示例圖:

它是專門(mén)為配置類服務(wù)的后處理器,主要任務(wù):
- 掃描所有
@Configuration類。 - 通過(guò)
postProcessBeanDefinitionRegistry()觸發(fā)配置類的掃描和解析 - 交給
ConfigurationClassParser解析成配置模型。 - 交給
ConfigurationClassBeanDefinitionReader轉(zhuǎn)換成BeanDefinition并注冊(cè)到容器。
4.ConfigurationClassParser的職責(zé)
當(dāng) ConfigurationClassPostProcessor 檢測(cè)到配置類時(shí),就會(huì)調(diào)用 ConfigurationClassParser 解析。
注意:它不是直接生成 BeanDefinition!
它的作用是:
讀取配置類上的元注解信息(通過(guò)
AnnotationMetadata)。根據(jù)不同注解做不同解析:
@Configuration→ 標(biāo)記為配置類,繼續(xù)處理內(nèi)部的@Bean方法。@Component→ 標(biāo)記為普通組件,后續(xù)注冊(cè)。@ComponentScan→ 觸發(fā)包掃描,找到其他@Component/@Service/@Controller。@Import→ 導(dǎo)入配置類或交給ImportSelector/ImportBeanDefinitionRegistrar。@ImportResource→ 加載 XML 配置。
遞歸解析,構(gòu)建出一棵配置類的內(nèi)部描述模型:
ConfigurationClass。
?? 它相當(dāng)于 語(yǔ)法分析器,把配置類源信息轉(zhuǎn)成中間表示。
5.ConfigurationClassBeanDefinitionReader的職責(zé)
接收
ConfigurationClassParser解析出來(lái)的ConfigurationClass模型。生成并注冊(cè)
BeanDefinition:@Bean方法 → 生成工廠方法對(duì)應(yīng)的 BeanDefinition。@Import導(dǎo)入的類 → 注冊(cè)。- 包掃描結(jié)果的組件 → 注冊(cè)。
將這些
BeanDefinition放入BeanDefinitionRegistry,等待容器實(shí)例化。
?? 它相當(dāng)于 代碼生成器,把中間表示落地成可用的 Bean 定義。
6. 整體鏈路總結(jié)
SpringApplication.run()→ 創(chuàng)建ApplicationContext。refresh()→ 執(zhí)行invokeBeanFactoryPostProcessors()。ConfigurationClassPostProcessor介入。ConfigurationClassParser解析配置類 → 生成ConfigurationClass模型。ConfigurationClassBeanDefinitionReader將模型轉(zhuǎn)化為BeanDefinition。BeanDefinitionRegistry注冊(cè)所有 生成的BeanDefinition。- 容器實(shí)例化 → Bean 生效。
?? 核心記憶
ConfigurationClassParser:負(fù)責(zé)解析配置類 → 生成ConfigurationClass模型。ConfigurationClassBeanDefinitionReader:負(fù)責(zé)將模型轉(zhuǎn)為BeanDefinition并注冊(cè)。- 最終
@Configuration/@Component/@Bean等注解能生效,是因?yàn)檫@套機(jī)制在容器刷新時(shí)自動(dòng)執(zhí)行。
核心流程圖總結(jié)
refresh()
↓ // 容器核心刷新流程入口
invokeBeanFactoryPostProcessors()
↓ // 執(zhí)行 BeanFactoryPostProcessor,增強(qiáng) BeanFactory
ConfigurationClassPostProcessor
↓ // 識(shí)別并處理 @Configuration、@ComponentScan、@Import 等配置類
ConfigurationClassParser
↓ // 解析配置類注解,生成 ConfigurationClass 模型(中間表示)
ConfigurationClassBeanDefinitionReader
↓ // 將 ConfigurationClass 轉(zhuǎn)換為 BeanDefinition
BeanDefinitionRegistry(注冊(cè) BeanDefinition)
↓ // 將 BeanDefinition 注冊(cè)到 IOC 容器
IOC 容器實(shí)例化 Bean
↓ // 根據(jù) BeanDefinition 實(shí)例化對(duì)象,完成依賴注入并放入單例池到此這篇關(guān)于SpringBoot注解生效原理全解析的文章就介紹到這了,更多相關(guān)SpringBoot注解生效原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Cloud重試機(jī)制與各組件的重試總結(jié)
這篇文章主要給大家介紹了關(guān)于Spring Cloud中重試機(jī)制與各組件的重試的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11
java項(xiàng)目jar包與jdk的版本不兼容的問(wèn)題解決
這篇文章主要介紹了java項(xiàng)目jar包與jdk的版本不兼容的問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10
Struts2實(shí)現(xiàn)對(duì)action請(qǐng)求對(duì)象的攔截操作方法
這篇文章主要介紹了Struts2實(shí)現(xiàn)對(duì)action請(qǐng)求對(duì)象的攔截操作方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-11-11
Struts2學(xué)習(xí)筆記(8)-Result常用類型
這篇文章主要介紹Struts2中Result四種常用的類型的用法,希望能給大家做一個(gè)參考。2016-06-06
布隆過(guò)濾器詳解以及其在Java中的實(shí)際應(yīng)用
布隆過(guò)濾器是一種數(shù)據(jù)結(jié)構(gòu),比較巧妙的概率型數(shù)據(jù)結(jié)構(gòu)(probabilistic data structure),特點(diǎn)是高效地插入和查詢,這篇文章主要給大家介紹了關(guān)于布隆過(guò)濾器詳解以及其在Java中的實(shí)際應(yīng)用,需要的朋友可以參考下2023-12-12
java中 利用正則表達(dá)式提取( )內(nèi)內(nèi)容
本篇文章,小編為大家介紹關(guān)于java中 利用正則表達(dá)式提取( )內(nèi)內(nèi)容,有需要的朋友可以參考一下2013-04-04
在SpringMVC框架下實(shí)現(xiàn)文件的上傳和下載示例
本篇文章主要介紹了在SpringMVC框架下實(shí)現(xiàn)文件的上傳和下載示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-02-02
Java實(shí)現(xiàn)導(dǎo)入csv的示例代碼
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)導(dǎo)入csv的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03

