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

Spring IoC 容器核心原理:從 BeanFactory 到 ApplicationContext 的演進

     編輯:Java 相關知識

前言

IoC (Inversion of Control,控制反轉) 是 Spring 框架的核心設計哲學,將對象創建、依賴管理、生命週期控制權從應用代碼移交給容器。本文深度解析 Spring IoC 容器的核心架構、BeanDefinition 註冊、依賴解析、生命週期管理、擴展點機制等核心原理。

一、IoC 容器核心架構

1. 核心接口層次

BeanFactory (根接口)
├─ getBean(name) / getBean(type)
├─ containsBean(name)
├─ isSingleton(name) / isPrototype(name)
├─ getType(name)
└─ getAliases(name)

↓ 擴展
ListableBeanFactory
├─ getBeanNamesForType(type)
├─ getBeanNamesForAnnotation(annotation)
└─ getBeanDefinitionNames()

↓ 擴展
HierarchicalBeanFactory
├─ getParentBeanFactory()
└─ containsLocalBean(name)

↓ 擴展
ConfigurableBeanFactory (配置能力)
├─ registerSingleton(name, object)
├─ registerBeanDefinition(name, BeanDefinition)
├─ addBeanPostProcessor(processor)
├─ setClassLoader(classLoader)
├─ addPropertyEditorRegistrar(registrar)
└─ addEmbeddedValueResolver(resolver)

↓ 擴展
AutowireCapableBeanFactory (自動裝配)
├─ createBean(clazz)
├─ autowireBean(bean)
├─ initializeBean(bean, name)
├─ applyBeanPostProcessorsBeforeInitialization()
└─ applyBeanPostProcessorsAfterInitialization()

↓ 終極擴展
ApplicationContext (企業級上下文)
├─ 繼承以上所有
├─ getEnvironment()           → EnvironmentCapable
├─ getMessage(code, args, locale) → MessageSource
├─ publishEvent(event)        → ApplicationEventPublisher
├─ getResources(pattern)      → ResourcePatternResolver
├─ start() / stop()           → Lifecycle
└─ getId() / getDisplayName() → 身份標識

2. 核心實現類:DefaultListableBeanFactory

  • 地位:Spring IoC 容器的 核心實現,實現了 ConfigurableListableBeanFactory 接口
  • 核心數據結構:
    • beanDefinitionMap:`ConcurrentHashMap` - Bean 定義註冊表
    • singletonObjects:`ConcurrentHashMap` - 一級緩存 (成品單例)
    • earlySingletonObjects:`ConcurrentHashMap` - 二級緩存 (早期暴露單例,解決循環依賴)
    • singletonFactories:`ConcurrentHashMap>` - 三級緩存 (ObjectFactory,用於 AOP 代理)
    • registeredSingletons:`LinkedHashSet` - 已註冊單例名稱集合

二、BeanDefinition:Bean 的元數據模型

1. 核心屬性

public class BeanDefinition {
    // 基礎屬性
    String beanClassName;           // 全限定類名
    String scope;                   // singleton / prototype / request / session
    boolean lazyInit;               // 延遲初始化
    String factoryBeanName;         // FactoryBean 名稱
    String factoryMethodName;       // 工廠方法名
    
    // 依賴關係
    ConstructorArgumentValues constructorArgumentValues; // 構造器參數
    MutablePropertyValues propertyValues;                // Setter 參數
    String[] dependsOn;              // 依賴的其他 Bean (強制初始化順序)
    boolean autowireCandidate;       // 是否作為自動裝配候選
    boolean primary;                 // 優先自動裝配
    
    // 生命週期
    String initMethodName;           // 初始化方法
    String destroyMethodName;        // 銷毀方法
    
    // 運行時狀態
    volatile Object beanClass;       // 解析後的 Class 對象
    boolean synthetic;               // 內部合成 Bean (如 aop:config 生成)
    int role;                        // ROLE_APPLICATION / ROLE_SUPPORT / ROLE_INFRASTRUCTURE
}

2. BeanDefinition 註冊來源

來源類型解析器/處理器典型場景
XML <bean>XmlBeanDefinitionReader → BeanDefinitionParserDelegate傳統 XML 配置
@Component 掃描ClassPathBeanDefinitionScanner → AnnotatedBeanDefinitionReader註解驅動開發
@Bean 方法ConfigurationClassPostProcessor → ConfigurationClassBeanDefinitionReaderJava Config
@ImportImportBeanDefinitionRegistrar 實現類模塊化配置、自動配置
動態註冊BeanDefinitionRegistryPostProcessor → registerBeanDefinition()框架擴展、條件註冊

三、容器啟動核心流程:refresh()

1. AbstractApplicationContext.refresh() 模板方法

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 1. 準備階段:初始化屬性源、驗證必需屬性
        prepareRefresh();
        
        // 2. 核心:獲取/創建 BeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        
        // 3. 配置 BeanFactory 標準上下文特性
        prepareBeanFactory(beanFactory);
        
        try {
            // 4. 子類擴展點:後置處理 BeanFactory
            postProcessBeanFactory(beanFactory);
            
            // 5. 調用 BeanFactoryPostProcessor (關鍵擴展點)
            invokeBeanFactoryPostProcessors(beanFactory);
            
            // 6. 註冊 BeanPostProcessor (另一關鍵擴展點)
            registerBeanPostProcessors(beanFactory);
            
            // 7. 初始化消息源 (i18n)
            initMessageSource();
            
            // 8. 初始化事件廣播器
            initApplicationEventMulticaster();
            
            // 9. 子類擴展點:初始化特定 Bean (如 MVC 請求映射)
            onRefresh();
            
            // 10. 註冊監聽器
            registerListeners();
            
            // 11. 核心:預實例化所有非懶加載單例 Bean
            finishBeanFactoryInitialization(beanFactory);
            
            // 12. 完成刷新:發布 ContextRefreshedEvent、啟動 Lifecycle Bean
            finishRefresh();
        } catch (BeansException ex) {
            // 銷毀已創建單例、發布 ContextClosedEvent
            destroyBeans();
            cancelRefresh(ex);
            throw ex;
        }
    }
}

2. 關鍵階段深度解析

階段 5:invokeBeanFactoryPostProcessors - Bean 定義修改期

// 典型實現:ConfigurationClassPostProcessor (處理 @Configuration/@Bean/@ComponentScan)
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        // 1. 解析 @Configuration 類
        // 2. 處理 @ComponentScan → 掃描組件 → 註冊 BeanDefinition
        // 3. 處理 @Import → 導入配置類/ImportSelector/ImportBeanDefinitionRegistrar
        // 4. 處理 @Bean 方法 → 註冊 BeanDefinition
    }
    
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 處理 @PropertySource、@EnableAspectJAutoProxy 等
    }
}

// PropertySourcesPlaceholderConfigurer:解析 ${...} 佔位符
// 自定義:實現 BeanFactoryPostProcessor 可在 Bean 實例化前修改 BeanDefinition

階段 6:registerBeanPostProcessors - Bean 實例化攔截期

// 核心接口
public interface BeanPostProcessor {
    // 初始化前:可返回代理對象、修改屬性
    Object postProcessBeforeInitialization(Object bean, String beanName);
    
    // 初始化後:AOP 代理創建、驗證、記錄日誌
    Object postProcessAfterInitialization(Object bean, String beanName);
}

// 關鍵內建實現 (按優先級排序):
// 1. PriorityOrdered → Ordered → 無序
// 2. InstantiationAwareBeanPostProcessor (擴展:預實例化、屬性注入攔截)
// 3. DestructionAwareBeanPostProcessor (擴展:銷毀前回調)

// 典型應用:
// - AutowiredAnnotationBeanPostProcessor:處理 @Autowired/@Value/@Inject
// - CommonAnnotationBeanPostProcessor:處理 @PostConstruct/@PreDestroy/@Resource
// - PersistenceAnnotationBeanPostProcessor:處理 @PersistenceContext/@PersistenceUnit
// - AsyncAnnotationBeanPostProcessor:處理 @Async 創建代理
// - TransactionAnnotationBeanPostProcessor:處理 @Transactional 創建事務代理
// - AnnotationAwareAspectJAutoProxyCreator:AOP 代理創建核心

階段 11:finishBeanFactoryInitialization - 單例實例化期

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 1. 初始化轉換服務
    beanFactory.setConversionService(new DefaultConversionService());
    
    // 2. 註冊內嵌值解析器 (解析 ${...} #{...})
    beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    
    // 3. 初始化 LoadTimeWeaver (AspectJ LTW)
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String name : weaverAwareNames) {
        getBean(name); // 觸發實例化
    }
    
    // 4. 核心循環:預實例化所有非懶加載 singleton
    beanFactory.preInstantiateSingletons();
}

四、Bean 實例化完整生命週期

1. 完整流程圖

getBean(beanName)
    ↓
1. 循環依賴檢查 (beforePrototypeCreation / afterPrototypeCreation)
    ↓
2. 合併 BeanDefinition (getMergedLocalBeanDefinition - 父子繼承合併)
    ↓
3. 依賴處理 (dependsOn → 遞歸初始化依賴 Bean)
    ↓
4. 作用域分發
    ├─ Singleton → getSingleton(beanName, () -> createBean(...))
    ├─ Prototype → createBean(beanName, bd, args)
    ├─ Request/Session/Application → 作用域特定獲取/創建
    └─ Custom Scope → Scope.get(beanName, factory)
    ↓
5. createBean 核心流程 (Singleton 為例)
    ├─ createBeanInstance()          → 實例化 (構造器/工廠方法/反射)
    ├─ populateBean()                → 屬性填充 (Setter/自動裝配/@Value)
    ├─ initializeBean()              → 初始化
    │    ├─ Aware 接口回調 (BeanNameAware, BeanFactoryAware, ApplicationContextAware...)
    │    ├─ BeanPostProcessor.postProcessBeforeInitialization()
    │    ├─ 初始化方法調用 (InitializingBean.afterPropertiesSet() / @PostConstruct / init-method)
    │    └─ BeanPostProcessor.postProcessAfterInitialization() → AOP 代理在此創建
    └─ 註冊銷毀回調 (DisposableBean / @PreDestroy / destroy-method)
    ↓
6. 返回成品對象 (原始 Bean 或 代理對象)

2. 循環依賴解決機制:三級緩存

// 單例模式下,A 依賴 B,B 依賴 A (Setter 注入)

步驟 1:A 實例化完成,放入三級緩存
singletonFactories.put("A", () -> getEarlyBeanReference("A", bd, bean));
// ObjectFactory 能返回早期引用 (若有 BeanPostProcessor 可能返回代理)

步驟 2:A 屬性填充,需要 B → getBean("B")
    ↓ B 實例化、屬性填充,需要 A → getBean("A")
    
步驟 3:getBean("A") 從三級緩存獲取
ObjectFactory factory = singletonFactories.get("A");
if (factory != null) {
    Object earlyRef = factory.getObject(); // 獲取早期引用 (可能是代理)
    earlySingletonObjects.put("A", earlyRef); // 升級到二級緩存
    singletonFactories.remove("A");           // 從三級移除
    return earlyRef;
}

步驟 4:B 完成初始化,持有 A 的早期引用
步驟 5:A 完成初始化,從二級緩存獲取自身,放入一級緩存
singletonObjects.put("A", bean);
earlySingletonObjects.remove("A");
registeredSingletons.add("A");

關鍵點:僅支援 單例 + Setter/字段注入 的循環依賴。構造器注入無法解決 (需打破循環或使用 @Lazy)。Prototype 作用域不支援循環依賴。

3. AOP 代理創建時機

// 在 BeanPostProcessor.postProcessAfterInitialization() 中
public class AnnotationAwareAspectJAutoProxyCreator extends AbstractAutoProxyCreator {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                return wrapIfNecessary(bean, beanName, cacheKey); // 創建代理
            }
        }
        return bean;
    }
}

// wrapIfNecessary() 核心邏輯:
// 1. 獲取目標類的所有切面 (Advisor)
// 2. 構建 ProxyFactory
// 3. 選擇代理方式:JDK Dynamic Proxy (實現接口) vs CGLIB (繼承類)
// 4. 返回目標對象的代理

五、核心擴展點總覽

擴展點接口調用時機典型用途實現示例
BeanFactoryPostProcessorBeanDefinition 註冊完成,Bean 實例化前修改 BeanDefinition、掃描註冊、解析佔位符ConfigurationClassPostProcessor, PropertySourcesPlaceholderConfigurer
BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor 之前動態註冊 BeanDefinitionConfigurationClassPostProcessor, 自定義註冊器
BeanPostProcessorBean 初始化前/後AOP 代理、依賴注入、驗證、修改屬性AutowiredAnnotationBPP, AsyncAnnotationBPP, AnnotationAwareAspectJAutoProxyCreator
InstantiationAwareBeanPostProcessor實例化前/後、屬性注入前返回代理跳過默認實例化、攔截屬性注入ConfigurationClassEnhancer (CGLIB 代理 @Configuration)
SmartInstantiationAwareBeanPostProcessor預測 Bean 類型、確定構造器優化自動裝配性能內部優化使用
FactoryBeangetBean() 時調用 getObject()封裝複雜對象創建邏輯SqlSessionFactoryBean, LocalContainerEntityManagerFactoryBean
InitializingBean / @PostConstruct屬性填充完成後業務初始化邏輯 (連接池預熱、緩存加載)自定義 Service 初始化
DisposableBean / @PreDestroy容器關閉前資源釋放 (關閉連接、線程池關閉)DataSource 銷毀、Scheduler 關閉
ApplicationListener / @EventListener事件發布時業務解耦、異步處理用戶註冊發送郵件、訂單創建發送 MQ

六、Spring Boot 自動配置原理:IoC 容器的極致應用

1. @EnableAutoConfiguration 核心流程

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class) // 關鍵:導入自動配置類
public @interface EnableAutoConfiguration { }

// AutoConfigurationImportSelector.selectImports()
public String[] selectImports(AnnotationMetadata annotationMetadata) {
    // 1. 讀取 META-INF/spring.factories
    // 2. 獲取 EnableAutoConfiguration 對應的所有配置類
    // 3. 過濾:@ConditionalOnClass/@ConditionalOnMissingBean/@ConditionalOnProperty...
    // 4. 排序:@AutoConfigureOrder / @AutoConfigureBefore/After
    // 5. 返回全限定類名數組
}

2. 條件裝配:@Conditional 系列

@Configuration
@ConditionalOnClass(DataSource.class)                    // 類路徑存在 DataSource
@ConditionalOnMissingBean(DataSource.class)              // 容器無 DataSource Bean
@ConditionalOnProperty(prefix="spring.datasource", name="url") // 配置了 url
@EnableConfigurationProperties(DataSourceProperties.class) // 綁定配置屬性
public class DataSourceAutoConfiguration {
    
    @Bean
    @ConditionalOnMissingBean
    public DataSource dataSource(DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().build(); // HikariCP 優先
    }
}

總結

Spring IoC 容器的核心價值在於:將「對象創建與裝配」從業務代碼中剝離,通過標準化的生命週期、擴展點、元數據模型,構建出高度可擴展、可維護的企業級應用框架。

掌握 BeanDefinition 元數據模型、refresh() 啟動流程、三級緩存解決循環依賴、BeanPostProcessor 擴展機制、條件裝配原理,是從「使用 Spring」進階為「精通 Spring」的必經之路。這些原理不僅指導日常開發排查疑難雜症,更是設計高質量框架、中間件的理論基石。

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