Spring 框架遵循開閉原則 (OCP),通過大量擴展介面讓開發者在不修改核心代碼的情況下定制 Bean 生命週期行為。本文系統梳理 Spring 中最常用、最核心的 Bean 擴展介面族群,含原理、執行順序、實戰場景與代碼範例。
public class LifecycleBean implements InitializingBean, DisposableBean {
private String name;
public void setName(String name) { this.name = name; }
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("1. InitializingBean.afterPropertiesSet() - 屬性設置完成後");
// 執行初始化邏輯:驗證屬性、建立連接、註冊監聽器等
}
@Override
public void destroy() throws Exception {
System.out.println("5. DisposableBean.destroy() - 容器關閉前");
// 執行銷毀邏輯:釋放資源、關閉連接、取消註冊等
}
}
執行順序:構造器 → Setter 注入 → afterPropertiesSet() → @PostConstruct → init-method → PostProcessor 後置 → 使用 → destroy() → @PreDestroy → destroy-method
優缺點:耦合 Spring API、效能高 (直接方法調用);@PostConstruct/@PreDestroy 為 JSR-250 標準、零耦合、反射調用 (微弱效能差異)。
| 介面 | 注入內容 | 典型用途 | 注入時機 |
|---|---|---|---|
BeanNameAware | String beanName (XML id 或註解 value) | 日誌標識、動態生成 Bean 名稱 | 屬性填充後、初始化前 |
BeanFactoryAware | BeanFactory (配置元數據訪問) | 程序化獲取其他 Bean、檢查 Bean 定義 | 屬性填充後、初始化前 |
ApplicationContextAware | ApplicationContext (完整容器上下文) | 最常用:獲取任意 Bean、發布事件、訪問資源、環境變量 | 屬性填充後、初始化前 |
EnvironmentAware | Environment (屬性配置、Profile) | 讀取外部化配置 | 屬性填充後、初始化前 |
ResourceLoaderAware | ResourceLoader (資源加載) | 加載 classpath/file/url 資源 | 屬性填充後、初始化前 |
MessageSourceAware | MessageSource (國際化) | 獲取國際化消息 | 屬性填充後、初始化前 |
public class AwareBean implements BeanNameAware, ApplicationContextAware, BeanFactoryAware {
private String beanName;
private ApplicationContext ctx;
private BeanFactory factory;
@Override public void setBeanName(String name) {
this.beanName = name;
System.out.println("Aware: BeanName = " + name);
}
@Override public void setApplicationContext(ApplicationContext ctx) {
this.ctx = ctx;
System.out.println("Aware: ApplicationContext 注入完成");
}
@Override public void setBeanFactory(BeanFactory factory) {
this.factory = factory;
System.out.println("Aware: BeanFactory 注入完成");
}
// 使用示例
public void doSomething() {
OtherBean bean = ctx.getBean(OtherBean.class); // 任意獲取 Bean
String prop = ctx.getEnvironment().getProperty("my.key");
ctx.publishEvent(new CustomEvent(this));
}
}
核心價值:開發者完全控制 Bean 實例化邏輯,返回類型為泛型 T,而非 FactoryBean 本身。
public class DataSourceFactoryBean implements FactoryBean<DataSource> {
private String url;
private String username;
private String password;
private String poolType; // HIKARI, DBCP, DRUID
// 核心方法:控制實例化邏輯
@Override
public DataSource getObject() throws Exception {
switch (poolType) {
case "HIKARI": return createHikari();
case "DRUID": return createDruid();
default: return createDbcp();
}
}
@Override public Class<?> getObjectType() { return DataSource.class; }
@Override public boolean isSingleton() { return true; } // 單例模式
// setter 省略
}
XML 配置:
<bean id="dataSource" class="com.example.DataSourceFactoryBean">
<property name="url" value="jdbc:mysql://localhost:3306/db"/>
<property name="poolType" value="HIKARI"/>
</bean>
注入時:@Resource DataSource dataSource 獲得的是 DataSource 實例;若需注入工廠本身:@Resource(name="&dataSource") DataSourceFactoryBean factory。
LocalSessionFactoryBean、SqlSessionFactoryBean、JndiObjectFactoryBean、PropertyPlaceholderConfigurer (實際繼承 BeanFactoryPostProcessor)作用:對容器中每個 Bean 初始化前後進行攔截、修改、替換、包裝。
public class MyBeanPostProcessor implements BeanPostProcessor {
// 初始化前:可修改屬性、返回代理對象 (如 AOP)
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("targetBean".equals(beanName)) {
System.out.println("BeforeInit: " + beanName);
// return Proxy.newProxyInstance(...); // 返回代理替換原 Bean
}
return bean; // 必須返回非 null
}
// 初始化後:AOP 代理在此生成、可進一步包裝
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("targetBean".equals(beanName)) {
System.out.println("AfterInit: " + beanName);
}
return bean;
}
}
關鍵點:
<bean class="com.example.MyBeanPostProcessor"/>null 導致 getBean() 返回 nullInstantiationAwareBeanPostProcessor → AutowiredAnnotationBeanPostProcessor → CommonAnnotationBeanPostProcessor → AspectJAutoProxyCreator (AOP) 等作用:在 Bean 實例化前,修改 Bean 定義元數據 (BeanDefinition),如屬性值、scope、lazy-init、甚至註冊新 BeanDefinition。
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 1. 修改現有 Bean 定義
BeanDefinition bd = beanFactory.getBeanDefinition("targetBean");
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE); // 改為原型
bd.setLazyInit(true);
bd.getPropertyValues().add("newProperty", "動態注入值");
// 2. 動態註冊新 Bean
GenericBeanDefinition gbd = new GenericBeanDefinition();
gbd.setBeanClass(NewBean.class);
gbd.getPropertyValues().add("name", "動態註冊");
beanFactory.registerBeanDefinition("dynamicBean", gbd);
// 3. 註冊 BeanPostProcessor (程序化)
beanFactory.addBeanPostProcessor(new MyBeanPostProcessor());
}
}
經典應用:
PropertyPlaceholderConfigurer / PropertySourcesPlaceholderConfigurer:解析 ${...} 佔位符ConfigurationClassPostProcessor:解析 @Configuration、@ComponentScan、@BeanCustomAutowireConfigurer:註冊自定義限定符執行順序:BeanFactoryPostProcessor (容器啟動早期,單次) → BeanPostProcessor (每個 Bean 初始化前後,多次)
繼承 BeanPostProcessor,增加實例化前後攔截:
postProcessBeforeInstantiation(Class<?> beanClass, String beanName):實例化前,返回非 null 可跳過預設實例化 (返回代理對象),AOP 核心機制postProcessAfterInstantiation(Object bean, String beanName):實例化後、屬性填充前,返回 false 可跳過屬性填充postProcessPropertyValues(PropertyValues pvs, ...):屬性填充前,可修改/過濾屬性值建議繼承 InstantiationAwareBeanPostProcessorAdapter 適配器,僅覆寫所需方法。
容器啟動
│
├─▶ BeanFactoryPostProcessor.postProcessBeanFactory() [一次性,修改 BeanDefinition]
│
├─▶ Bean 實例化 (構造器/工廠方法)
│ │
│ ├─▶ InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() [可返回代理跳過]
│ │
│ └─▶ InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() [可跳過屬性填充]
│
├─▶ 屬性填充 (Setter/DI)
│ │
│ └─▶ InstantiationAwareBeanPostProcessor.postProcessPropertyValues() [修改屬性值]
│
├─▶ Aware 介面回調 (BeanName/ApplicationContext/BeanFactory...)
│
├─▶ BeanPostProcessor.postProcessBeforeInitialization() [初始化前攔截]
│
├─▶ 初始化邏輯
│ ├─▶ InitializingBean.afterPropertiesSet()
│ ├─▶ @PostConstruct
│ └─▶ init-method
│
├─▶ BeanPostProcessor.postProcessAfterInitialization() [初始化後攔截,AOP 代理生成]
│
├─▶ Bean 就緒可用
│
└─▶ 容器關閉
│
├─▶ @PreDestroy
├─▶ DisposableBean.destroy()
└─▶ destroy-method
| 需求 | 推薦介面 | 關鍵提示 |
|---|---|---|
| Bean 初始化/銷毀邏輯 | @PostConstruct / @PreDestroy | 標準註解、零耦合、首選 |
| 需訪問容器設施 (獲取 Bean、發布事件、讀配置) | ApplicationContextAware | 最常用 Aware,注入後可隨意使用 |
| 動態控制 Bean 創建邏輯 (條件創建、多實現選擇) | FactoryBean | 返回類型為泛型 T,非工廠本身 |
| 修改 Bean 定義元數據 (scope、屬性值、動態註冊 Bean) | BeanFactoryPostProcessor | 容器啟動早期執行,影響所有後續 Bean |
| 攔截/包裝/替換 Bean 實例 (AOP、監控、驗證) | BeanPostProcessor | 對每個 Bean 生效,返回非 null |
| 控制實例化過程 (跳過實例化、跳過屬性填充、修改屬性) | InstantiationAwareBeanPostProcessor | 繼承 Adapter 適配器,AOP 核心機制 |
AbstractAutowireCapableBeanFactory.doCreateBean() — Bean 創建總入口AbstractAutowireCapableBeanFactory.createBeanInstance() — 實例化策略 (構造器/工廠/FactoryBean)AbstractAutowireCapableBeanFactory.populateBean() — 屬性填充AbstractAutowireCapableBeanFactory.initializeBean() — 初始化流程 (Aware、PostProcessor、初始化方法)AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization()AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization()DefaultListableBeanFactory.preInstantiateSingletons() — 單例預實例化入口ConfigurationClassPostProcessor — @Configuration 解析核心AutowiredAnnotationBeanPostProcessor — @Autowired 處理核心AspectJAutoProxyCreator — AOP 代理生成核心核心心法:Spring 擴展介面族群構成了框架的「插件系統」。理解各介面的執行時機、作用範圍、優先級順序,能讓你在需要定制框架行為時精準選擇切入點,而非硬編碼或複製粘貼。原始碼是最好的文檔,建議從
doCreateBean開始單步調試,親眼見證 Bean 誕生全過程。
掌握 Bean 擴展介面,是從「會用 Spring」進階為「懂 Spring、能魔改 Spring」的關鍵門檻。