首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring Bean 擴展介面深度解析:Aware、InitializingBean、FactoryBean、PostProcessor 全家族

     編輯:Java 綜合教學

Spring Bean 擴展介面深度解析:Aware、InitializingBean、FactoryBean、PostProcessor 全家族

Spring 框架遵循開閉原則 (OCP),通過大量擴展介面讓開發者在不修改核心代碼的情況下定制 Bean 生命週期行為。本文系統梳理 Spring 中最常用、最核心的 Bean 擴展介面族群,含原理、執行順序、實戰場景與代碼範例。

一、生命週期回調介面族群

1. InitializingBean / DisposableBean (Spring 專用介面)

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 標準、零耦合、反射調用 (微弱效能差異)。

2. Aware 介面族群 (感知容器基礎設施)

介面注入內容典型用途注入時機
BeanNameAwareString beanName (XML id 或註解 value)日誌標識、動態生成 Bean 名稱屬性填充後、初始化前
BeanFactoryAwareBeanFactory (配置元數據訪問)程序化獲取其他 Bean、檢查 Bean 定義屬性填充後、初始化前
ApplicationContextAwareApplicationContext (完整容器上下文)最常用:獲取任意 Bean、發布事件、訪問資源、環境變量屬性填充後、初始化前
EnvironmentAwareEnvironment (屬性配置、Profile)讀取外部化配置屬性填充後、初始化前
ResourceLoaderAwareResourceLoader (資源加載)加載 classpath/file/url 資源屬性填充後、初始化前
MessageSourceAwareMessageSource (國際化)獲取國際化消息屬性填充後、初始化前
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));
    }
}

二、工廠模式擴展介面

FactoryBean<T> (最靈活的 Bean 創建控制)

核心價值:開發者完全控制 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。

實際應用場景

  • Spring 內建:LocalSessionFactoryBean、SqlSessionFactoryBean、JndiObjectFactoryBean、PropertyPlaceholderConfigurer (實際繼承 BeanFactoryPostProcessor)
  • 動態代理創建、連接池選型、複雜對象組裝、第三方庫整合

三、後置處理器族群 (核心擴展點)

1. BeanPostProcessor (Bean 實例級攔截)

作用:對容器中每個 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;
    }
}

關鍵點:

  • XML 配置無需 id:<bean class="com.example.MyBeanPostProcessor"/>
  • 返回 null 導致 getBean() 返回 null
  • Spring 內建 Processor (按順序):InstantiationAwareBeanPostProcessor → AutowiredAnnotationBeanPostProcessor → CommonAnnotationBeanPostProcessor → AspectJAutoProxyCreator (AOP) 等

2. BeanFactoryPostProcessor (BeanDefinition 級元數據修改)

作用:在 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、@Bean
  • CustomAutowireConfigurer:註冊自定義限定符

執行順序:BeanFactoryPostProcessor (容器啟動早期,單次) → BeanPostProcessor (每個 Bean 初始化前後,多次)

3. InstantiationAwareBeanPostProcessor (實例化階段攔截)

繼承 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 核心機制

六、原始碼閱讀建議路徑

  1. AbstractAutowireCapableBeanFactory.doCreateBean() — Bean 創建總入口
  2. AbstractAutowireCapableBeanFactory.createBeanInstance() — 實例化策略 (構造器/工廠/FactoryBean)
  3. AbstractAutowireCapableBeanFactory.populateBean() — 屬性填充
  4. AbstractAutowireCapableBeanFactory.initializeBean() — 初始化流程 (Aware、PostProcessor、初始化方法)
  5. AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization()
  6. AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization()
  7. DefaultListableBeanFactory.preInstantiateSingletons() — 單例預實例化入口
  8. ConfigurationClassPostProcessor — @Configuration 解析核心
  9. AutowiredAnnotationBeanPostProcessor — @Autowired 處理核心
  10. AspectJAutoProxyCreator — AOP 代理生成核心

核心心法:Spring 擴展介面族群構成了框架的「插件系統」。理解各介面的執行時機、作用範圍、優先級順序,能讓你在需要定制框架行為時精準選擇切入點,而非硬編碼或複製粘貼。原始碼是最好的文檔,建議從 doCreateBean 開始單步調試,親眼見證 Bean 誕生全過程。

掌握 Bean 擴展介面,是從「會用 Spring」進階為「懂 Spring、能魔改 Spring」的關鍵門檻。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved