深入理解 Spring Bean 后處理器@Autowired 等注解的本質(zhì)(示例demo)
在日常開發(fā)中,我們幾乎每天都會(huì)用到 @Autowired、@Value、@Resource、@PostConstruct 等注解。
但你是否想過,這些“神奇”的注入和生命周期回調(diào)機(jī)制,是誰(shuí)在幕后完成的?
今天我們通過一個(gè)非常簡(jiǎn)潔的 Demo,一步步揭開 Spring Bean 后處理器的秘密。
一、代碼示例
package com.itheima.a04;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.context.support.GenericApplicationContext;
/*
* Bean 后處理器的作用演示
*/
public class A04 {
public static void main(String[] args) {
// 1?? 創(chuàng)建一個(gè)“干凈”的容器(沒有任何自動(dòng)注冊(cè)的組件)
GenericApplicationContext context = new GenericApplicationContext();
// 2?? 手動(dòng)注冊(cè)一些普通 Bean
context.registerBean("bean1", Bean1.class);
context.registerBean("bean2", Bean2.class);
context.registerBean("bean3", Bean3.class);
context.registerBean("bean4", Bean4.class);
// 3?? 配置容器的自動(dòng)注入解析策略(支持 @Value)
context.getDefaultListableBeanFactory()
.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
// 4?? 手動(dòng)注冊(cè)各種 Bean 后處理器
context.registerBean(AutowiredAnnotationBeanPostProcessor.class); // 負(fù)責(zé)解析 @Autowired 和 @Value
context.registerBean(CommonAnnotationBeanPostProcessor.class); // 負(fù)責(zé)解析 @Resource、@PostConstruct、@PreDestroy
ConfigurationPropertiesBindingPostProcessor.register(context.getDefaultListableBeanFactory()); // 負(fù)責(zé)解析 @ConfigurationProperties
// 5?? 初始化容器(執(zhí)行 BeanFactory 后處理器、添加 BeanPostProcessor、初始化所有單例 Bean)
context.refresh();
System.out.println(context.getBean(Bean1.class));
// 6?? 關(guān)閉容器,觸發(fā)銷毀回調(diào)
context.close();
/*
學(xué)到什么?
? 1. @Autowired、@Value、@Resource、@PostConstruct 等注解的功能,
都是由 Bean 后處理器在 Bean 生命周期階段完成的。
? 2. Bean 后處理器本身也是一種“插件機(jī)制”,可以擴(kuò)展 Spring 的核心行為。
*/
}
}二、Demo 核心邏輯解析
這段代碼其實(shí)干了三件事:
1?? 創(chuàng)建一個(gè)干凈的容器
GenericApplicationContext 是 Spring 提供的一個(gè)空白容器實(shí)現(xiàn)。
它不像 AnnotationConfigApplicationContext 那樣自動(dòng)注冊(cè)注解處理器、掃描包路徑或加載配置類。
換句話說(shuō),它是“白紙一張”,這就讓我們可以手動(dòng)控制 Spring 容器內(nèi)部機(jī)制。
GenericApplicationContext context = new GenericApplicationContext();
2?? 手動(dòng)注冊(cè) Bean 與處理器
正常情況下,Spring 會(huì)自動(dòng)幫你注冊(cè) AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor 等組件。
但這里我們手動(dòng)注冊(cè)它們,以便更清楚地看到它們的作用:
| 注冊(cè)組件 | 功能說(shuō)明 |
|---|---|
AutowiredAnnotationBeanPostProcessor | 解析 @Autowired、@Value |
CommonAnnotationBeanPostProcessor | 解析 @Resource、@PostConstruct、@PreDestroy |
ConfigurationPropertiesBindingPostProcessor | 解析 @ConfigurationProperties |
ContextAnnotationAutowireCandidateResolver | 支持 @Value("${}") 等表達(dá)式解析 |
這幾行代碼告訴我們:
?? Spring 并沒有“魔法”地識(shí)別這些注解,而是通過后處理器擴(kuò)展點(diǎn)去實(shí)現(xiàn)的。
3?? 初始化容器與銷毀
context.refresh() 會(huì)觸發(fā)以下流程:
- 執(zhí)行
BeanFactoryPostProcessor(工廠級(jí)別的增強(qiáng)) - 注冊(cè)所有
BeanPostProcessor - 實(shí)例化所有單例 Bean
- 在創(chuàng)建 Bean 的過程中,各個(gè)后處理器開始發(fā)揮作用,完成依賴注入與生命周期方法調(diào)用。
隨后,context.close() 會(huì)觸發(fā)銷毀階段,執(zhí)行:
@PreDestroy注解的方法DisposableBean接口方法- 自定義銷毀回調(diào)
三、結(jié)論:后處理器是 Spring 的靈魂
這個(gè) Demo 的意義非常深刻,它揭示了一個(gè)關(guān)鍵真相:
Spring 框架中幾乎所有“魔法”都是通過 Bean 后處理器(BeanPostProcessor)實(shí)現(xiàn)的。
下面是一個(gè)簡(jiǎn)單的關(guān)系圖,幫助理解:
Spring Bean 生命周期(精簡(jiǎn)版)
實(shí)例化前 → [InstantiationAwareBeanPostProcessor]
構(gòu)造方法執(zhí)行(實(shí)例化)
屬性注入 → [AutowiredAnnotationBeanPostProcessor]
初始化前 → [CommonAnnotationBeanPostProcessor 處理 @PostConstruct]
初始化后 → [AOP、代理增強(qiáng)等]
銷毀前 → [CommonAnnotationBeanPostProcessor 處理 @PreDestroy]四、總結(jié)
| 關(guān)鍵點(diǎn) | 說(shuō)明 |
|---|---|
| 后處理器是 Spring 可擴(kuò)展機(jī)制的核心 | 所有注解的功能其實(shí)都是“插件化”的 |
@Autowired 等注解不是語(yǔ)法糖,而是由后處理器解釋執(zhí)行的 | 運(yùn)行期反射完成依賴注入 |
容器生命周期由 refresh() 驅(qū)動(dòng) | 包括 Bean 定義加載、處理器注冊(cè)、Bean 實(shí)例化、初始化等步驟 |
| 你也可以編寫自己的 BeanPostProcessor | 比如自定義注解、監(jiān)控 Bean 加載時(shí)間、實(shí)現(xiàn) AOP 增強(qiáng)等 |
五、總結(jié)一句話
Spring 的強(qiáng)大,不在于注解本身,而在于它提供了可以“掛接任意邏輯”的生命周期擴(kuò)展機(jī)制。
到此這篇關(guān)于深入理解 Spring Bean 后處理器@Autowired 等注解的本質(zhì)的文章就介紹到這了,更多相關(guān)Spring Bean @Autowired 注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Spring框架原理之實(shí)例化bean和@Autowired實(shí)現(xiàn)原理方式
- 在 Spring Boot 中使用 @Autowired和 @Bean注解的示例詳解
- Spring的@Bean和@Autowired組合使用詳解
- Spring注解中@Autowired和@Bean的區(qū)別詳解
- 詳解Spring bean的注解注入之@Autowired的原理及使用
- 詳解SpringBoot 多線程處理任務(wù) 無(wú)法@Autowired注入bean問題解決
- 解決SpringBoot項(xiàng)目使用多線程處理任務(wù)時(shí)無(wú)法通過@Autowired注入bean問題
相關(guān)文章
如何基于springboot-admin實(shí)現(xiàn)后臺(tái)監(jiān)控
這篇文章主要介紹了如何基于springboot-admin實(shí)現(xiàn)后臺(tái)監(jiān)控,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04
基于SpringBoot和Vue3的博客平臺(tái)的用戶注冊(cè)與登錄功能實(shí)現(xiàn)
本教程將指導(dǎo)您如何使用Spring?Boot和Vue3實(shí)現(xiàn)用戶注冊(cè)與登錄功能。我們將使用Spring?Boot作為后端框架,Vue3作為前端框架,同時(shí)使用MySQL作為數(shù)據(jù)庫(kù),感興趣的朋友可以參考一下2023-04-04
SpringBoot+Redis隊(duì)列實(shí)現(xiàn)Java版秒殺的示例代碼
本文主要介紹了SpringBoot+Redis隊(duì)列實(shí)現(xiàn)Java版秒殺的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
詳解如何讓Spring MVC顯示自定義的404 Not Found頁(yè)面
這篇文章主要介紹了詳解如何讓Spring MVC顯示自定義的404 Not Found頁(yè)面,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2018-10-10
java?SpringBoot注解@Async不生效的解決方法
大家好,本篇文章主要講的是java?SpringBoot注解@Async不生效的解決方法,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-01-01
Java多線程編程實(shí)戰(zhàn)之模擬大量數(shù)據(jù)同步
這篇文章主要介紹了Java多線程編程實(shí)戰(zhàn)之模擬大量數(shù)據(jù)同步,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02
一文看懂springboot實(shí)現(xiàn)短信服務(wù)功能
項(xiàng)目中的短信服務(wù)基本上上都會(huì)用到,簡(jiǎn)單的注冊(cè)驗(yàn)證碼,消息通知等等都會(huì)用到。這篇文章主要介紹了springboot 實(shí)現(xiàn)短信服務(wù)功能,需要的朋友可以參考下2019-10-10

