淺析 Spring 中 FactoryBean 的實現與使用

淺析 Spring 中 FactoryBean 的實現與使用

  • 一、FactoryBean核心機制剖析
  • 二、高級應用場景與實戰
  • 三、框架級應用案例解析
  • 四、FactoryBean常見面試題

在這里插入圖片描述

一、FactoryBean核心機制剖析

1. 本質與雙重角色

FactoryBean是Spring容器中用于定制化對象創建的核心接口(org.springframework.beans.factory.FactoryBean),其設計體現了兩個關鍵特征:

  • 工廠模式:通過getObject()方法動態生成目標對象
  • 容器托管:FactoryBean本身作為Spring Bean被容器管理,支持依賴注入和生命周期回調

2. 接口方法詳解

public interface FactoryBean<T> {T getObject() throws Exception;    // 核心工廠方法Class<?> getObjectType();          // 決定自動注入的類型匹配default boolean isSingleton() {    // 控制對象作用域return true;}
}

運行機制:
Spring容器初始化時,若檢測到Bean實現FactoryBean接口,會通過getObject()生成目標對象。通過&前綴獲取工廠實例本身(如getBean("&myFactory")

3. 源碼級工作流程

參考Spring源碼的Bean創建流程:

  1. Bean實例化AbstractAutowireCapableBeanFactory.createBeanInstance()創建FactoryBean實例
  2. 對象生成:在getObjectForBeanInstance()方法中調用getObject()生成目標對象
  3. 緩存處理:單例對象存入factoryBeanObjectCache,多例對象每次新建

關鍵源碼片段(簡化):

// AbstractBeanFactory.doGetBean()
Object beanInstance = getSingleton(beanName);
if (beanInstance instanceof FactoryBean) {return getObjectFromFactoryBean((FactoryBean<?>) beanInstance, beanName);
}

二、高級應用場景與實戰

1. 多例對象動態生成

public class PrototypeToolFactory implements FactoryBean<Tool> {@Override public boolean isSingleton() {return false; // 每次請求新實例}@Overridepublic Tool getObject() {return new Tool(UUID.randomUUID().toString());}
}

應用場景:數據庫連接池、線程不安全對象的按需創建

2. 手動配置代理(AOP場景)

(ProxyFactoryBean 是 Spring AOP 中用于 手動配置代理對象的核心類;而動態代理底層是基于AnnotationAwareAspectJAutoProxyCreator實現)

public class ServiceProxyFactory implements FactoryBean<Object> {private Object target;@Overridepublic Object getObject() {return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),(proxy, method, args) -> {System.out.println("[Before] Method: " + method.getName());Object result = method.invoke(target, args);System.out.println("[After] Result: " + result);return result;});}
}

實現原理:Spring AOP的ProxyFactoryBean即采用類似機制生成代理對象

3. 延遲初始化策略

public class LazyDataSourceFactory implements FactoryBean<DataSource> {private boolean initialized = false;private DataSource dataSource;@Overridepublic DataSource getObject() {if (!initialized) {initializeDataSource(); // 首次調用時初始化initialized = true;}return dataSource;}
}

優勢:優化啟動速度,按需加載重量級資源

三、框架級應用案例解析

1. MyBatis SqlSessionFactoryBean

核心邏輯:

  • 實現InitializingBean確保屬性設置完成后構建SqlSessionFactory
  • 通過buildSqlSessionFactory()解析XML配置、Mapper映射
  • 集成Spring事務管理

2. Spring Cloud FeignClientFactoryBean

實現機制:

  • 動態生成Feign客戶端接口代理
  • 整合Ribbon負載均衡、Hystrix熔斷
  • 通過Targeter.target()生成最終代理對象

3. Spring AOP ProxyFactoryBean

(ProxyFactoryBean 是 Spring AOP 中用于 手動配置代理對象的核心類;而動態代理底層是基于AnnotationAwareAspectJAutoProxyCreator實現)

<bean id="personTarget" class="com.example.PersonImpl"/>
<bean id="myAdvisor" class="com.example.MyAdvisor"/><bean id="personProxy" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="personTarget"/><property name="proxyInterfaces" value="com.example.Person"/><property name="interceptorNames"><list><value>myAdvisor</value></list></property>
</bean>

工作流程:

  • 配置Advisor(切面)和Advice(增強)
  • 通過getObject()生成JDK/CGLIB代理
  • 將攔截器鏈織入代理對象

四、FactoryBean常見面試題

1. BeanFactory 和 FactoryBean 的區別?

維度BeanFactoryFactoryBean
角色Spring 容器根接口,管理所有 Bean特殊 Bean,用于生成其他對象
獲取方式getBean(“beanName”) 直接獲取 BeangetBean(“beanName”) 獲取目標對象,&beanName 獲取工廠
設計目標提供容器基礎功能(如依賴注入)擴展復雜對象的創建邏輯(如代理、動態配置)
典型實現ApplicationContextSqlSessionFactoryBean、ProxyFactoryBean

2. FactoryBean 的初始化時機?

  • 普通 Bean 階段:FactoryBean 實例在 Spring 容器初始化時創建。
  • 目標對象階段:目標對象(getObject() 生成)在首次調用 getBean() 時創建,支持懶加載(@Lazy)。 源碼位置:AbstractBeanFactory.getObjectForBeanInstance()getObjectFromFactoryBean()

3. 如何通過 FactoryBean 實現多例對象?

  • 重寫方法isSingleton() 返回 false,每次調用 getObject() 生成新實例。

  • 示例

    public class PrototypeFactory implements FactoryBean<MyObject> {@Overridepublic boolean isSingleton() { return false; }@Overridepublic MyObject getObject() { return new MyObject(); }
    }
    

應用場景:線程不安全對象(如數據庫連接)、動態配置對象

4. FactoryBean 在 MyBatis 中的應用?

  • 案例:SqlSessionFactoryBean
  • 核心流程
    • 實現 FactoryBean<SqlSessionFactory>,在 getObject() 中解析 MyBatis 配置。
    • 集成 Spring 事務管理,通過 InitializingBean 確保屬性初始化完成

5. 如何獲取 FactoryBean 自身實例?

  • 語法:在 Bean 名稱前添加 & 前綴,例如 context.getBean("&myFactory")
  • 原理:Spring 容器通過 BeanFactory.FACTORY_BEAN_PREFIX 標識工廠實例

6. FactoryBean 與 @Bean 注解的區別?

維度FactoryBean@Bean
實現方式需實現接口,編寫 getObject() 邏輯通過注解聲明,直接返回對象實例
對象生成動態生成(如代理、復雜初始化)直接實例化(簡單對象)
獲取方式beanName 獲取目標對象,&beanName 獲取工廠直接通過 beanName 獲取實例
生命周期支持單例/多例控制默認單例,可通過 @Scope 修改

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

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

相關文章

vue3 element-plus 輸入框回車跳轉頁面問題處理

問題描述&#xff1a; 當頁面搜索條件只有一個的情況下&#xff0c;輸入框不管有沒有值&#xff0c;回車后會跳轉頁面 解決辦法&#xff0c;給表單添加 submit.prevent <el-form ref"ruleForm" :model"search" label-width"120px" class&qu…

(51單片機)LCD展示動畫(延時函數)(LCD1602教程)

前言&#xff1a; 前面我們說過&#xff0c;之前LCD1602模塊有點難&#xff0c;但是現在&#xff0c;我們通過幾遍博客的學習&#xff0c;今天來講一下LCD1602的原理 演示視頻&#xff1a; LCD1602流動 源代碼&#xff1a; main.c #include <STC89C5xRC.H> #include &q…

深入了解 OpenIddict:實現 OAuth 2.0 和 OpenID Connect 協議的 .NET 庫

在現代 Web 開發中&#xff0c;身份驗證和授權是安全性的重要組成部分。隨著對安全性的要求不斷增加&#xff0c;OAuth 2.0 和 OpenID Connect&#xff08;OIDC&#xff09;協議已經成為許多應用程序的標準身份驗證方式。而 OpenIddict&#xff0c;作為一個用于實現 OAuth 2.0 …

【C++游戲引擎開發】第30篇:物理引擎(Bullet)—軟體動力學系統

一、軟體動力學理論體系 1.1 連續體力學基礎 1.1.1 變形梯度張量 物體運動可描述為映射函數: x = ? ( X , t ) \mathbf{x} = \phi(\mathbf{X},t) x

Android Compose 層疊布局(ZStack、Surface)源碼深度剖析(14)

Android Compose 層疊布局&#xff08;ZStack、Surface&#xff09;源碼深度剖析 一、引言 在 Android 應用開發領域&#xff0c;用戶界面&#xff08;UI&#xff09;的設計與實現一直是至關重要的環節。隨著技術的不斷演進&#xff0c;Android Compose 作為一種全新的聲明式…

性能優化實踐:內存優化技巧

性能優化實踐&#xff1a;內存優化技巧 在Flutter應用開發中&#xff0c;內存優化是提升應用性能的關鍵環節之一。本文將從實戰角度深入探討Flutter內存優化的各種技巧&#xff0c;幫助你構建高性能的Flutter應用。 一、內存分析工具使用 1. DevTools內存分析器 啟動DevTool…

2025-05-07 Unity 網絡基礎8——UDP同步異步通信

文章目錄 1 UDP 概述1.1 通信流程1.2 TCP 與 UDP1.3 UDP 分包1.4 UDP 黏包 2 同步通信2.1 服務端2.2 客戶端2.3 測試 3 異步通信3.1 Bgin / End 方法3.2 Async 方法 1 UDP 概述 1.1 通信流程 ? 客戶端和服務端的流程如下&#xff1a; 創建套接字 Socket。用 Bind() 方法將套…

如何減少鎖競爭并細化鎖粒度以提高 Rust 多線程程序的性能?

在并發編程中&#xff0c;鎖&#xff08;Lock&#xff09;是一種常用的同步機制&#xff0c;用于保護共享數據免受多個線程同時訪問造成的競態條件&#xff08;Race Condition&#xff09;。然而&#xff0c;不合理的鎖使用會導致嚴重的性能瓶頸&#xff0c;特別是在高并發場景…

AGV智能搬運機器人:富唯智能引領工業物流高效變革

在智能制造與工業4.0深度融合的今天&#xff0c;物流環節的高效與精準已成為企業核心競爭力的關鍵。富唯智能憑借其自主研發的AGV智能搬運機器人&#xff0c;以創新技術重塑工業物流標準&#xff0c;助力企業實現降本增效的跨越式發展。 一、技術突破&#xff1a;精準導航與智能…

K8s 資源分類

K8s 資源分類圖譜 內置資源的分類 1、工作負載相關&#xff1a; Pod&#xff1a;最小的部署單元&#xff0c;包含一個或多個容器。 Deployment&#xff1a;管理無狀態應用的副本和滾動更新。 StatefulSet&#xff1a;適用于有狀態應用&#xff08;如數據庫&#xff09;&#…

VLM-AD:通過視覺語言模型監督實現端到端自動駕駛

《VLM-AD: End-to-End Autonomous Driving through Vision-Language Model Supervision》2024年12月發表&#xff0c;來自Cruise和美國東北大學的論文。 人類駕駛員依靠常識推理來駕馭多樣化和動態的現實世界場景。現有的端到端&#xff08;E2E&#xff09;自動駕駛&#xff0…

目標檢測中的損失函數(三) | SIoU WIoUv1 WIoUv2 WIoUv3

&#x1f680;該系列將會持續整理和更新BBR相關的問題&#xff0c;如有錯誤和不足懇請大家指正&#xff0c;歡迎討論&#xff01;&#xff01;&#xff01; SCYLLA-IoU&#xff08;SIoU&#xff09;來自掛在2022年arxiv上的文章&#xff1a;《SIoU Loss: More Powerful Learnin…

http Status 400 - Bbad request 網站網頁經常報 HTTP 400 錯誤,清緩存后就好了的原因

目錄 一、HTTP 400 錯誤的常見成因(一)問題 URL(二)緩存與 Cookie 異常(三)請求頭信息錯誤(四)請求體數據格式不正確(五)文件尺寸超標(六)請求方法不當二、清緩存為何能奏效三、其他可以嘗試的解決辦法(一)重新檢查 URL(二)暫時關閉瀏覽器插件(三)切換網絡環…

【DeepMLF】具有可學習標記的多模態語言模型,用于情感分析中的深度融合

這是一篇我完全看不懂的論文,寫的好晦澀,適合唬人,所以在方法部分我以大白話為主 abstract 在多模態情感分析(MSA)中,多模態融合已經得到了廣泛的研究,但融合深度和多模態容量分配的作用還沒有得到充分的研究。在這項工作中,我們將融合深度、可擴展性和專用多模容量作…

【ASP.net】在Windows 11上安裝IIS并測試C# Web項目的踩坑實錄

摘要 多年未接觸.NET技術棧的田辛老師&#xff0c;最近因項目需求重新搭建測試環境。本文記錄了Windows 11環境下安裝IIS服務的全過程&#xff0c;以及一個讓開發者抓狂的“空白頁面”問題的解決方案。 1. 基礎環境配置 工欲善其事&#xff0c;必先利其器。本次環境搭建選擇…

【IP101】圖像特征提取技術:從傳統方法到深度學習的完整指南

&#x1f31f; 特征提取魔法指南 &#x1f3a8; 在圖像處理的世界里&#xff0c;特征提取就像是尋找圖像的"指紋"&#xff0c;讓我們能夠識別和理解圖像的獨特性。讓我們一起來探索這些神奇的特征提取術吧&#xff01; &#x1f4da; 目錄 基礎概念 - 特征的"體…

HybridCLR 詳解:Unity 全平臺原生 C# 熱更新方案

HybridCLR&#xff08;原 Huatuo&#xff09;是 Unity 平臺革命性的熱更新解決方案&#xff0c;它通過擴展 Unity 的 IL2CPP 運行時&#xff0c;實現了基于原生 C# 的完整熱更新能力。下面從原理到實踐全面解析這一技術。 一、核心原理剖析 1. 技術架構 原始 IL2CPP 流程&am…

機器學習——邏輯回歸ROC練習

一、 題目要求&#xff1a; 給定以下二分類模型的預測結果&#xff0c;手動繪制ROC曲線并計算AUC值&#xff1a; y_true [0, 1, 0, 1, 0, 1] # 真實標簽&#xff08;0負類&#xff0c;1正類&#xff09; y_score [0.2, 0.7, 0.3, 0.6, 0.1, 0.8] # 模型預測得分 代碼展示…

Python項目源碼69:Excel數據篩選器1.0(tkinter+sqlite3+pandas)

功能說明&#xff1a;以下是一個使用Tkinter和Pandas實現的完整示例&#xff0c;支持Excel數據讀取、雙表格展示和高級條件篩選功能&#xff1a; 1.文件操作&#xff1a;點擊"打開文件"按鈕選擇Excel文件&#xff08;支持.xlsx和.xls格式&#xff09;&#xff0c;自…

php8 枚舉使用教程

簡介 PHP 從 8.1 開始原生支持枚舉&#xff08;enum&#xff09;&#xff0c;這是 PHP 向類型安全和現代語言特性邁進的重要一步。枚舉可以定義一組有窮的、不可變的常量集合&#xff0c;常用于表示狀態值、選項類型等。 基礎語法 PHP 支持兩種類型的枚舉&#xff1a; 純枚…