Spring Framework源碼解析——BeanFactory


版權聲明

  • 本文原創作者:谷哥的小弟
  • 作者博客地址:http://blog.csdn.net/lfdfhl

在這里插入圖片描述

1. BeanFactory 概述

BeanFactory 是 Spring IoC 容器的最基礎接口,它定義了獲取、配置和管理 Bean 的核心方法。它是 Spring 框架中容器體系的頂層接口之一,提供了最基本的依賴注入功能。

1.1 接口定義

public interface BeanFactory {String FACTORY_BEAN_PREFIX = "&";Object getBean(String name) throws BeansException;<T> T getBean(String name, Class<T> requiredType) throws BeansException;<T> T getBean(Class<T> requiredType) throws BeansException;boolean containsBean(String name);boolean isSingleton(String name) throws BeansException;boolean isPrototype(String name) throws BeansException;boolean isTypeMatch(String name, ResolvableType typeToMatch) throws BeansException;Class<?> getType(String name) throws BeansException;String[] getAliases(String name);
}
  • getBean:獲取容器中已注冊的 Bean 實例。
  • containsBean:判斷某個名稱的 Bean 是否存在。
  • isSingleton / isPrototype:判斷 Bean 的作用域。
  • getType / isTypeMatch:獲取或匹配 Bean 的類型。
  • getAliases:獲取某個 Bean 的所有別名。

1.2 與 ApplicationContext 的關系

  • BeanFactory 是 Spring 容器的基礎接口。
  • ApplicationContext 是其子接口,擴展了 BeanFactory 的功能,增加了國際化、事件發布、資源加載等高級功能。
  • BeanFactory 是“按需加載”,而 ApplicationContext 是“預加載單例 Bean”。

2. 核心實現類

DefaultListableBeanFactory 是 Spring 中最常用的 BeanFactory 實現類,它實現了 BeanDefinitionRegistry 接口,支持注冊和管理 Bean 定義。

2.1. 核心屬性

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactoryimplements ConfigurableListableBeanFactory, BeanDefinitionRegistry {private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
}
  • beanDefinitionMap:存儲 Bean 名稱與 BeanDefinition 的映射關系。
  • beanDefinitionNames:存儲所有已注冊的 Bean 名稱列表。

2.2 注冊 Bean 定義

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {this.beanDefinitionMap.put(beanName, beanDefinition);if (!this.beanDefinitionNames.contains(beanName)) {this.beanDefinitionNames.add(beanName);}
}
  • 將 Bean 定義放入 beanDefinitionMap 中。
  • 將 Bean 名稱加入 beanDefinitionNames 列表。

3. Bean 的加載過程

getBean() 是獲取 Bean 的核心方法。其調用鏈如下:

getBean()doGetBean()getSingleton()createBean()doCreateBean()populateBean()initializeBean()

3.1 doGetBean() 方法

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {final String beanName = transformedBeanName(name);Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {// 如果是 FactoryBean,處理 & 前綴bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);} else {// 創建 Beanbean = createBean(beanName, mbd, args);}return (T) bean;
}
  • transformedBeanName:處理 & 前綴(用于獲取 FactoryBean 本身)。
  • getSingleton:嘗試從單例緩存中獲取 Bean。
  • createBean:如果不存在,調用 createBean 創建新實例。

3.2 單例 Bean 的創建

3.2.1 getSingleton() 方法

public Object getSingleton(String beanName) {return this.singletonObjects.get(beanName);
}
  • singletonObjects:是一個 Map<String, Object>,緩存所有已創建的單例 Bean。

3.2.2 創建 Bean 的流程

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {// 1. 解析 Bean 的 ClassClass<?> resolvedClass = resolveBeanClass(mbd, beanName);// 2. 實例化 BeanObject beanInstance = instantiateBean(beanName, mbd);// 3. 屬性注入populateBean(beanName, mbd, instanceWrapper);// 4. 初始化 BeanexposedObject = initializeBean(beanName, exposedObject, mbd);// 5. 注冊為單例addSingleton(beanName, exposedObject);return exposedObject;
}

4. Bean 的生命周期

Spring 中 Bean 的生命周期由 BeanFactory 管理,其流程如下:

  1. 實例化:通過構造方法或工廠方法創建 Bean 實例。
  2. 屬性注入:注入依賴的其他 Bean 或配置值。
  3. 初始化前回調:如 BeanNameAwareBeanFactoryAware 等接口的回調。
  4. 初始化方法調用:如 @PostConstructInitializingBean 接口或配置的 init-method
  5. 使用 Bean:Bean 可以被使用。
  6. 銷毀前回調:如 @PreDestroyDisposableBean 接口或配置的 destroy-method
  7. 銷毀 Bean:清理資源。

初始化 Bean 示例如下:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {// 調用 Aware 接口方法invokeAwareMethods(beanName, bean);// 調用初始化方法if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}invokeInitMethods(beanName, wrappedBean, mbd);if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
}

5. 工廠 Bean(FactoryBean)

FactoryBean 是一種特殊的 Bean,它本身是一個工廠,用于創建其他 Bean。

5.1 接口定義

public interface FactoryBean<T> {T getObject() throws Exception;Class<?> getObjectType();boolean isSingleton();
}

5.2 獲取 FactoryBean 實例

Object bean = getBean("&myFactoryBean");
assertTrue(bean instanceof FactoryBean);
  • 使用 & 前綴獲取 FactoryBean 本身。
  • 不帶前綴則獲取其 getObject() 返回的 Bean。

6. Bean 的作用域(Scope)

Spring 支持多種作用域,包括:

  • singleton(默認):每個容器中只有一個實例。
  • prototype:每次調用 getBean() 都返回一個新實例。
  • request / session(Web 作用域):每個請求或會話一個實例。

作用域實現機制如下:

public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {String beanName = transformedBeanName(name);RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);return mbd.isSingleton();
}
  • RootBeanDefinition 中保存了 Bean 的作用域配置。

7. BeanFactory 的擴展機制

7.1 BeanFactoryPostProcessor

允許在 Bean 實例化之前修改 BeanDefinition

public interface BeanFactoryPostProcessor {void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

示例:

public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {BeanDefinition beanDef = beanFactory.getBeanDefinition("myBean");beanDef.setScope(BeanDefinition.SCOPE_PROTOTYPE);}
}

7.2 BeanPostProcessor

允許在 Bean 實例化前后進行干預。

public interface BeanPostProcessor {default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}
}

8. BeanFactory 與 ApplicationContext 的對比

特性BeanFactoryApplicationContext
初始化時機按需加載(懶加載)啟動時預加載單例 Bean
功能特性僅提供基本的依賴注入提供國際化、事件發布、資源加載等高級功能
資源加載僅支持類路徑加載支持多種資源加載方式(如 Ant 路徑)
擴展點支持需手動注冊 BeanPostProcessor 等組件自動注冊并調用擴展點

9. 核心代碼示例與解釋

9.1 手動注冊 Bean 定義并獲取 Bean

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
RootBeanDefinition definition = new RootBeanDefinition(MyBean.class);
factory.registerBeanDefinition("myBean", definition);MyBean bean = factory.getBean("myBean", MyBean.class);
System.out.println(bean);
  • 創建 DefaultListableBeanFactory
  • 定義 BeanDefinition
  • 注冊 Bean 定義。
  • 獲取 Bean 實例。

9.2 使用 BeanFactoryPostProcessor 修改 Bean 定義

factory.addBeanPostProcessor(new CustomBeanFactoryPostProcessor());
  • 將自定義的 BeanFactoryPostProcessor 添加到容器中。

10. 總結

BeanFactory 是 Spring IoC 容器的核心接口之一,它提供了最基本的依賴注入功能。其設計體現了模塊化、可擴展性和靈活性,是構建 Spring 容器體系的基礎。通過理解其源碼結構、生命周期管理、Bean 加載機制以及擴展機制,開發者可以更深入地掌握 Spring 的運行原理,并在實際項目中更好地進行配置和優化。實踐建議如下:

  1. 優先使用 ApplicationContext:在企業級應用中推薦使用,因其提供了更全面的功能。
  2. 理解 BeanFactory 的懶加載機制:適用于資源受限的場景。
  3. 合理使用 BeanPostProcessorBeanFactoryPostProcessor:用于擴展容器行為。
  4. 避免過度依賴 BeanFactory 的底層 API:保持代碼的可測試性和可維護性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/92166.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/92166.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/92166.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C# 計算梯形面積和周長的程序(Program to calculate area and perimeter of Trapezium)

梯形是至少有一對邊平行&#xff0c;其他兩條邊可以不平行的四邊形。平行邊稱為梯形的底&#xff0c;其他兩條邊稱為梯形的腿。平行邊之間的垂直距離稱為梯形的高。公式 &#xff1a; 梯形面積&#xff1a; 0.5 * (a b) * h梯形周長&#xff1a; a b c d例子&#xff1a; 輸…

【計算機考研(408)- 數據結構】數組和特殊矩陣

數組和特殊矩陣 數組 數組的定義 數組是由n(n>1)個相同類型的數據元素構成的有限序列。每個數據元素稱為一個數組元素&#xff0c;每個元素在n個線性關系中的序號稱之為該元素的下標&#xff0c;下標的取值范圍稱為數組的維界。 數組是[[線性表]]的推廣&#xff0c;一維數組…

Agent架構與工作原理:理解智能體的核心機制

Agent架構與工作原理&#xff1a;深入理解智能體的核心機制 AI Agent的核心組成部分 一個完整的AI Agent通常由以下幾個核心模塊組成&#xff1a; 1. 規劃模塊&#xff08;Planning Module&#xff09; 規劃模塊是Agent的"大腦"&#xff0c;負責制定行動策略。它接收…

解決vscode中vue格式化后縮進太小的問題,并去除分號 - 設置Vetur tabSize從2到4,設置prettier取消分號semi

效果圖 左邊原來的&#xff0c;右邊是設置后的效果 實現步驟 安裝插件 Vetur 安裝插件 prettier Vscode > 文件 > 首選項 > 設置 搜索vetur > 找到比較下面的“Vetur > Format > Options: Tab Size” > 設置縮進為4 在附近找到“Vetur > Format: De…

計算機發展史:電子管時代的輝煌與局限

在計算機的發展歷程中&#xff0c;電子管時代猶如一顆璀璨的流星&#xff0c;短暫卻耀眼。它接過了機械計算裝置的接力棒&#xff0c;以電子管為核心元件&#xff0c;開啟了計算機的電子化征程&#xff0c;為后續的計算機發展奠定了堅實的基礎。這段從 20 世紀 40 年代到 50 年…

div和span區別

區別1區別2App.vue代碼 <template><div class"container"><h1>&#x1f3af; DIV 和 SPAN 標簽的區別演示</h1><!-- 第一部分&#xff1a;基本區別演示 --><section class"demo-section"><h2>&#x1f4e6; 1. …

channel_up和lane_up

一、channel_up 1.當aurora通道完成初始化&#xff0c;channel準備發送或者接收數據的時候拉高 2.channel_up屬于協議的鏈路層 3.當所有的通道的lane_up都成功拉高&#xff0c;并且完成通道綁定channel bonding,就拉高channel_up二、lane_up 1.lane初始化成功后拉高&#xff1b…

GDPR合規團隊協作軟件:保障企業數據安全的關鍵

隨著數據隱私問題日益成為全球關注的焦點&#xff0c;GDPR&#xff08;General Data Protection Regulation&#xff0c;通用數據保護條例&#xff09; 的實施成為企業在數據管理中的一項重要法律要求。特別是對于需要在團隊之間協作并共享信息的企業來說&#xff0c;選擇合規的…

【圖像質量評價指標】信噪比(Signal-to-Noise Ratio,SNR)

文章目錄一、基本定義二、判斷圖像信噪比是否過低&#xff08;經驗值&#xff0c;僅供參考&#xff09;三、SNR與圖像質量指標關系四、評估方法 代碼復現 —— 評估一張圖像的信噪比&#xff08;1&#xff09;有參考圖像&#xff08;推薦&#xff09;&#xff08;2&#xff09…

Java 實現 TCP 一發一收通信

在網絡編程中&#xff0c;TCP&#xff08;傳輸控制協議&#xff09;憑借其可靠傳輸的特性&#xff0c;成為需要確保數據完整性場景的核心選擇。本文將基于一段 Java 代碼實例&#xff0c;全面解析 TCP 單向通信的實現邏輯&#xff0c;幫助開發者掌握 TCP 編程的基礎框架與底層原…

docker-compose啟動前后端分離項目(單機)

&#x1f31f;docker-compose啟動前后端 &#x1f4c1;準備文件 xzs-mysql.sql&#xff08;數據庫腳本&#xff09;xzs-3.9.0.jar&#xff08;后端代碼&#xff09;application-prod.yml&#xff08;后端配置文件&#xff09;entry.sh&#xff08;后端啟動腳本&#xff09;exam…

有關Mysql數據庫的總結

MySQL概念MySQL的理論知識概念數據庫就是用來存儲和管理數據的倉庫&#xff01;數據庫分類層次型數據庫樹型結構&#xff0c;一個子記錄可以有一個父記錄&#xff0c;一個父記錄可以有多個子記錄&#xff0c;類似一個二叉樹&#xff0c;但是一個父節點可以不止兩個子節點&#…

復制docker根目錄遇到的權限問題

環境 ubuntu20.04, 普通用戶使用sudo權限。 需求 linux系統上&#xff0c;默認的docker跟目錄在/var/lib/docker目錄下&#xff0c;但是根分區太小。想要將docker根目錄挪到其它磁盤&#xff0c;防止以后鏡像和容器增加后磁盤滿了。 操作 先停止所有docker容器&#xff0c;然后…

git-子倉操作

為什么為什么要將代碼倉作為子模塊&#xff1f;有什么優勢&#xff1f;精確版本控制&#xff1a;父倉記錄子倉的commit哈希值&#xff0c;確保代碼版本固定&#xff0c;避免隱式升級導致的兼容性問題模塊化管理&#xff1a;將獨立倉庫作為子模塊嵌入父倉&#xff0c;實現代碼物…

代數——第5章——線性算子之應用(Michael Artin)

第 5 章 線性算子之應用 (Applications of Linear Operators) By relieving the brain from all unnecessary work, a good notation sets it free to concentrate on more advanced problems.( 通過減輕大腦所有不必要的工作&#xff0c;良好的符號可以讓大腦集中精力解決…

Pytorch02:深度學習基礎示例——貓狗識別

一、第三方庫介紹庫/模塊功能torch提供張量操作、自動求導、優化算法、神經網絡模塊等基礎設施。torchvision計算機視覺工具集&#xff0c;提供預訓練模型、數據集、圖像轉換等功能。datasets (torchvision)用于加載常見數據集&#xff08;如 ImageNet、CIFAR-10、MNIST&#x…

spring簡單項目實戰

項目路徑 modelspackage com.qcby.demo1;import com.qcby.service.UserService; import com.qcby.service.UserServiceImpl;public class Dfactory {public UserService createUs(){System.out.println("實例化工廠的方式...");return new UserServiceImpl();} }pack…

ServBay for Windows 1.4.0 發布:新增MySQL、PostgreSQL等數據庫自定義配置

各位 Windows 平臺的開發者們&#xff0c; ServBay 始終致力于為您打造一個強大、高效且靈活的本地開發環境。距離上次更新僅過去短短一周&#xff0c;經過我們技術團隊的快速開發&#xff0c;我們正式推出了 ServBay for Windows 1.4.0 版本。 專業開發者不僅需要一個能用的環…

python網絡爬蟲小項目(爬取評論)超級簡單

python網絡爬蟲小項目&#xff08;爬取評論&#xff09;超級簡單 學習python網絡爬蟲的完整路徑&#xff1a; &#xff08;第一章&#xff09; python網絡爬蟲(第一章/共三章&#xff1a;網絡爬蟲庫、robots.txt規則&#xff08;防止犯法&#xff09;、查看獲取網頁源代碼)-…

本周大模型新動向:獎勵引導、多模態代理、鏈式思考推理

點擊藍字關注我們AI TIME歡迎每一位AI愛好者的加入&#xff01;01Iterative Distillation for Reward-Guided Fine-Tuning of Diffusion Models in Biomolecular Design本文提出了一種用于生物分子設計中獎勵引導生成的擴散模型微調框架。擴散模型在建模復雜、高維數據分布方面…