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

深入理解 Spring 系列三:DefaultListableBeanFactory 核心源碼解析

     編輯:Java 綜合教學

深入理解 Spring 系列三:DefaultListableBeanFactory 核心源碼解析

Spring 容器啟動過程中,Bean 定義被解析為 `BeanDefinition` 並註冊到 `DefaultListableBeanFactory`。本文深入剖析 **BeanFactory 接口體系、DefaultListableBeanFactory 核心屬性、單例/原型 Bean 存儲機制、getBean 核心流程**,構建 Spring IOC 容器核心認知。

一、BeanFactory 接口:IOC 容器的頂層契約

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&"; // 用於獲取 FactoryBean 本身而非其產品

    Object getBean(String name) throws BeansException;
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException;
    Object getBean(String name, Object... args) throws BeansException;
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

    boolean containsBean(String name);
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    String[] getAliases(String name);
}

核心職責:**Bean 實例的獲取、類型檢查、別名解析**。不包含刷新、事件發布、國際化等高級功能 (屬於 ApplicationContext)。

二、DefaultListableBeanFactory 類圖與核心屬性

DefaultListableBeanFactory
    │  實現 BeanDefinitionRegistry (註冊 BeanDefinition)
    │  繼承 AbstractAutowireCapableBeanFactory (自動裝配能力)
    │  繼承 AbstractBeanFactory (基礎 getBean 模板)
    │  實現 ConfigurableListableBeanFactory (配置能力)
    │  繼承 DefaultSingletonBeanRegistry (單例註冊表)  ◀── 關鍵
    ▼

核心屬性 (源碼片段)

// BeanDefinition 註冊表:beanName -> BeanDefinition
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

// BeanDefinition 註冊順序列表
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

// 單例對象緩存:beanName -> Bean Instance (來自 DefaultSingletonBeanRegistry)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

// 早期單例對象緩存 (解決循環依賴)
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

// 正在創建的單例集合
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

三、Bean 註冊流程

  1. 解析配置 (XML/@Component/@Bean) → 生成 `BeanDefinition` (含類名、屬性值、構造參數、scope、lazy-init、depends-on、factory-method 等元數據)
  2. 調用 `registerBeanDefinition(String beanName, BeanDefinition bd)`
  3. 存入 `beanDefinitionMap`、追加 `beanDefinitionNames`、清除合併緩存

四、getBean 核心流程 (簡化版)

public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

protected <T> T doGetBean(String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) {
    // 1. 轉換 beanName (處理 FactoryBean & 前綴、別名)
    String beanName = transformedBeanName(name);

    // 2. 嘗試從單例緩存獲取 (含早期曝光對象)
    Object sharedInstance = getSingleton(beanName, () -> null);
    if (sharedInstance != null) {
        return getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    // 3. 原型/其他作用域:創建新實例
    // 4. 合併父 BeanDefinition (若有 parent)
    // 5. 解析依賴 (depends-on) 先創建依賴
    // 6. 委託 createBean(beanName, mbd, args) 創建實例
    //    ├─ 實例化 (構造器/工廠方法)
    //    ├─ 屬性填充 (自動裝配、@Value、SpEL)
    //    ├─ 初始化 (@PostConstruct、InitializingBean、init-method、AOP 代理)
    //    └─ 註冊銷毀回調 (DisposableBean、destroy-method)
    // 7. 類型檢查、後處理、返回
}

五、單例模式的雙重檢查鎖實現 (DefaultSingletonBeanRegistry)

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    // 快速路徑:直接從緩存讀取
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null) {
        synchronized (this.singletonObjects) {
            // 雙重檢查
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                // 標記正在創建
                beforeSingletonCreation(beanName);
                try {
                    singletonObject = singletonFactory.getObject(); // 真正創建邏輯
                } catch (Exception ex) {
                    throw new BeanCreationException(beanName, ex);
                } finally {
                    afterSingletonCreation(beanName);
                }
                if (singletonObject != null) {
                    addSingleton(beanName, singletonObject); // 存入緩存
                }
            }
        }
    }
    return singletonObject;
}

六、循環依賴解決:三級緩存機制

緩存級別Map存儲內容生命週期
一級singletonObjects完全初始化完成的單例 Bean容器生命週期
二級earlySingletonObjects早期曝光的單例 Bean (實例化後、屬性填充前)創建過程中
三級singletonFactoriesObjectFactory (能產生早期引用,用於 AOP 代理)創建過程中

流程:A 創建 → 實例化 → **放入三級緩存** → 屬性填充 (需 B) → B 創建 → 實例化 → 放入三級緩存 → 屬性填充 (需 A) → **從三級緩存獲取 A 早期引用 (若 A 被代理則獲取代理對象)** → B 完成 → 存入一級緩存 → A 繼續完成 → 存入一級緩存。

七、總結

`DefaultListableBeanFactory` 是 Spring IOC 容器的**核心引擎**:

  • **註冊表**:`beanDefinitionMap` 存儲所有 Bean 元數據
  • **單例池**:`singletonObjects` 緩存單例實例,三級緩存解決循環依賴
  • **模板方法**:`doGetBean` 定義獲取流程,子類/擴展點控制創建細節
  • **可配置性**:繼承體系賦予自動裝配、類型轉換、後處理、作用域擴展能力

理解其源碼結構,是掌握 Spring 容器啟動、Bean 生命週期、循環依賴、AOP 代理創建時機的鑰匙。建議配合 IDE 斷點調試 `getBean`、`createBean`、`populateBean`、`initializeBean` 核心節點,將靜態代碼轉化為動態認知。

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