深入理解 Spring Bean 后處理器@Autowired 等注解的本質(zhì)(示例demo)
在日常開發(fā)中,我們幾乎每天都會用到 @Autowired、@Value、@Resource、@PostConstruct 等注解。
但你是否想過,這些“神奇”的注入和生命周期回調(diào)機(jī)制,是誰在幕后完成的?
今天我們通過一個非常簡潔的 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)建一個“干凈”的容器(沒有任何自動注冊的組件)
GenericApplicationContext context = new GenericApplicationContext();
// 2?? 手動注冊一些普通 Bean
context.registerBean("bean1", Bean1.class);
context.registerBean("bean2", Bean2.class);
context.registerBean("bean3", Bean3.class);
context.registerBean("bean4", Bean4.class);
// 3?? 配置容器的自動注入解析策略(支持 @Value)
context.getDefaultListableBeanFactory()
.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
// 4?? 手動注冊各種 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)建一個干凈的容器
GenericApplicationContext 是 Spring 提供的一個空白容器實(shí)現(xiàn)。
它不像 AnnotationConfigApplicationContext 那樣自動注冊注解處理器、掃描包路徑或加載配置類。
換句話說,它是“白紙一張”,這就讓我們可以手動控制 Spring 容器內(nèi)部機(jī)制。
GenericApplicationContext context = new GenericApplicationContext();
2?? 手動注冊 Bean 與處理器
正常情況下,Spring 會自動幫你注冊 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor 等組件。
但這里我們手動注冊它們,以便更清楚地看到它們的作用:
| 注冊組件 | 功能說明 |
|---|---|
AutowiredAnnotationBeanPostProcessor | 解析 @Autowired、@Value |
CommonAnnotationBeanPostProcessor | 解析 @Resource、@PostConstruct、@PreDestroy |
ConfigurationPropertiesBindingPostProcessor | 解析 @ConfigurationProperties |
ContextAnnotationAutowireCandidateResolver | 支持 @Value("${}") 等表達(dá)式解析 |
這幾行代碼告訴我們:
?? Spring 并沒有“魔法”地識別這些注解,而是通過后處理器擴(kuò)展點(diǎn)去實(shí)現(xiàn)的。
3?? 初始化容器與銷毀
context.refresh() 會觸發(fā)以下流程:
- 執(zhí)行
BeanFactoryPostProcessor(工廠級別的增強(qiáng)) - 注冊所有
BeanPostProcessor - 實(shí)例化所有單例 Bean
- 在創(chuàng)建 Bean 的過程中,各個后處理器開始發(fā)揮作用,完成依賴注入與生命周期方法調(diào)用。
隨后,context.close() 會觸發(fā)銷毀階段,執(zhí)行:
@PreDestroy注解的方法DisposableBean接口方法- 自定義銷毀回調(diào)
三、結(jié)論:后處理器是 Spring 的靈魂
這個 Demo 的意義非常深刻,它揭示了一個關(guān)鍵真相:
Spring 框架中幾乎所有“魔法”都是通過 Bean 后處理器(BeanPostProcessor)實(shí)現(xiàn)的。
下面是一個簡單的關(guān)系圖,幫助理解:
Spring Bean 生命周期(精簡版)
實(shí)例化前 → [InstantiationAwareBeanPostProcessor]
構(gòu)造方法執(zhí)行(實(shí)例化)
屬性注入 → [AutowiredAnnotationBeanPostProcessor]
初始化前 → [CommonAnnotationBeanPostProcessor 處理 @PostConstruct]
初始化后 → [AOP、代理增強(qiáng)等]
銷毀前 → [CommonAnnotationBeanPostProcessor 處理 @PreDestroy]四、總結(jié)
| 關(guān)鍵點(diǎn) | 說明 |
|---|---|
| 后處理器是 Spring 可擴(kuò)展機(jī)制的核心 | 所有注解的功能其實(shí)都是“插件化”的 |
@Autowired 等注解不是語法糖,而是由后處理器解釋執(zhí)行的 | 運(yùn)行期反射完成依賴注入 |
容器生命周期由 refresh() 驅(qū)動 | 包括 Bean 定義加載、處理器注冊、Bean 實(shí)例化、初始化等步驟 |
| 你也可以編寫自己的 BeanPostProcessor | 比如自定義注解、監(jiān)控 Bean 加載時間、實(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中Integer.parseInt和Integer.valueOf區(qū)別小結(jié)
在Java中,Integer.parseInt()和Integer.valueOf()都可以將字符串轉(zhuǎn)換為整數(shù)類型,那么他們有哪些區(qū)別呢,本文就來詳細(xì)的介紹一下2023-09-09
SpringMVC JSON數(shù)據(jù)交互實(shí)現(xiàn)過程解析
這篇文章主要介紹了SpringMVC JSON數(shù)據(jù)交互實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-10-10
Java并發(fā)工具之CountDownLatch使用詳解
這篇文章主要介紹了Java并發(fā)工具之CountDownLatch使用詳解,通過使用 CountDownLatch可以使當(dāng)前線程阻塞,等待其他線程完成給定任務(wù),可以類比旅游團(tuán)導(dǎo)游要等待所有的游客到齊后才能去下一個景點(diǎn),需要的朋友可以參考下2023-12-12
java8 forEach結(jié)合Lambda表達(dá)式遍歷 List操作
這篇文章主要介紹了java8 forEach結(jié)合Lambda表達(dá)式遍歷 List操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
Java中ResponseBodyEmitter的實(shí)現(xiàn)
這篇文章主要介紹了Java中ResponseBodyEmitter的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
一篇文章帶你理解Java Spring三級緩存和循環(huán)依賴
這篇文章主要介紹了淺談Spring 解決循環(huán)依賴必須要三級緩存嗎,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-09-09

