Sprinig源碼解析

前言

??Spring 框架是 Java 企業級開發的基石,其源碼設計體現了模塊化、擴展性和靈活性。以下從 IoC 容器、AOP 實現、核心模塊和關鍵設計模式四個角度對 Spring 源碼進行深度解析,幫助理解其底層機制。即使Spring會使用的人見得就能使用。

一、IoC 容器源碼解析

??IoC(控制反轉)是 Spring 的核心,其核心接口是 BeanFactory 和 ApplicationContext。

1.1. Bean 的生命周期

Spring 管理 Bean 的完整生命周期,關鍵步驟如下:

1.Bean 定義加載:

  • 通過 BeanDefinitionReader(如 XmlBeanDefinitionReader)讀取 XML 或注解配置,解析為 BeanDefinition 對象。

2.Bean 實例化:

  • 調用 InstantiationStrategy(默認 CglibSubclassingInstantiationStrategy)創建 Bean 實例。
  • 反射或 CGLIB 動態生成子類(用于處理構造方法注入或 AOP 代理)。

3.依賴注入:

  • 通過 AutowiredAnnotationBeanPostProcessor 處理 @Autowired 注解。
  • 使用 CommonAnnotationBeanPostProcessor 處理 @Resource 等 JSR-250 注解。

4.初始化:

  • 調用 InitializingBean.afterPropertiesSet() 或自定義 init-method。
  • 應用 BeanPostProcessor.postProcessBeforeInitialization() 和 postProcessAfterInitialization()。

5.銷毀:

  • 調用 DisposableBean.destroy() 或自定義 destroy-method。

1.2. BeanFactory 與 ApplicationContext

  • BeanFactory:
  • 基礎容器接口(DefaultListableBeanFactory 是默認實現)。
  • 延遲加載 Bean,首次調用 getBean() 時實例化。
    ApplicationContext:
  • 擴展自 BeanFactory,提供企業級功能(國際化、事件發布、資源加載等)。
  • 默認在啟動時預初始化所有單例 Bean(通過 AbstractApplicationContext.refresh())。

1.3. 源碼流程示例

// 核心入口:AbstractApplicationContext.refresh()
public void refresh() {// 1. 加載 BeanDefinitionobtainFreshBeanFactory();// 2. 調用 BeanFactoryPostProcessorinvokeBeanFactoryPostProcessors();// 3. 注冊 BeanPostProcessorregisterBeanPostProcessors();// 4. 初始化單例 BeanfinishBeanFactoryInitialization(beanFactory);
}

二、AOP 實現源碼解析

Spring AOP 基于動態代理實現,支持 JDK 動態代理和 CGLIB。

2.1. AOP 核心組件

  • Pointcut:定義切點(哪些方法需要被增強)。
  • Advice:定義增強邏輯(前置、后置、環繞等)。
  • Advisor:組合 Pointcut 和 Advice。
  • AopProxy:生成代理對象的接口(JdkDynamicAopProxy 或 ObjenesisCglibAopProxy)。

2.2. 代理創建流程

??1.在 Bean 初始化階段,AbstractAutoProxyCreator(實現 BeanPostProcessor)攔截 Bean 的創建。
??2.根據 Pointcut 匹配 Bean 的方法,生成代理對象。
??3.調用代理對象的方法時,觸發 MethodInterceptor 鏈式執行。

2.3. 源碼示例

// JdkDynamicAopProxy 的 invoke() 方法
public Object invoke(Object proxy, Method method, Object[] args) {// 獲取攔截器鏈List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);// 創建 MethodInvocation 并執行MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);return invocation.proceed();
}

三、核心模塊解析

3.1. 事務管理(@Transactional)

  • 實現原理:

    • 通過 TransactionInterceptor 攔截方法調用。
    • 使用 PlatformTransactionManager(如 DataSourceTransactionManager)管理事務。
  • 關鍵代碼:

// TransactionAspectSupport.invokeWithinTransaction()
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) {TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);try {Object result = invocation.proceedWithInvocation();commitTransactionAfterReturning(txInfo);return result;} catch (Throwable ex) {completeTransactionAfterThrowing(txInfo, ex);throw ex;}
}

3.2. 事件機制(ApplicationEvent)

  • 核心類:

    • ApplicationEventPublisher:發布事件。
    • ApplicationListener:監聽事件。
  • 流程:

    • 調用 publishEvent() 發布事件。
    • 通過 SimpleApplicationEventMulticaster 廣播事件到所有匹配的監聽器。

3.3. SpEL(Spring Expression Language)

  • 解析流程:
    • 使用 SpelExpressionParser 解析表達式。
    • 通過 StandardEvaluationContext 提供上下文變量。

四、關鍵設計模式

  1. 模板方法模式
  • 應用場景:AbstractApplicationContext.refresh() 定義了容器初始化的骨架,子類可重寫特定步驟(如 AnnotationConfigWebApplicationContext)。
  • 示例代碼:
public abstract class AbstractApplicationContext {public void refresh() {// 模板方法obtainFreshBeanFactory();prepareBeanFactory(beanFactory);postProcessBeanFactory(beanFactory);// ...}
}
  1. 工廠模式
  • 應用場景:BeanFactory 是工廠接口,DefaultListableBeanFactory 是具體實現。
  1. 代理模式
  • 應用場景:AOP 動態代理、ProxyFactoryBean 創建代理對象。
  1. 觀察者模式
  • 應用場景:事件發布與監聽機制。

五、調試 Spring 源碼的建議

1.入口示例:

// 基于注解的容器初始化
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = context.getBean(UserService.class);
userService.save();

2.關鍵斷點:

  • AbstractApplicationContext.refresh():容器初始化的核心入口。
  • AbstractAutowireCapableBeanFactory.createBean():Bean 實例化的關鍵邏輯。
  • JdkDynamicAopProxy.invoke():AOP 代理方法調用。
  • TransactionInterceptor.invoke():事務管理的攔截邏輯。

六、Spring 源碼設計哲學

??1.開閉原則:通過擴展點(如 BeanPostProcessor)支持功能擴展,無需修改核心代碼。

??2.單一職責:模塊高度解耦(如 BeanFactory 負責 Bean 管理,ApplicationContext 提供企業級功能)。

??3.約定優于配置:通過默認配置減少用戶工作量(如自動掃描 @Component 注解)。

總結

??Spring源碼通過模塊化設計和經典設計模式實現了高度靈活性和擴展性:

  • IoC 容器:以 BeanFactory 為核心,通過 BeanDefinition 和 BeanPostProcessor 管理 Bean 生命周期。
  • AOP:基于動態代理和攔截器鏈實現切面編程。
  • 事務與事件:通過攔截器和觀察者模式提供企業級功能。
  • 擴展機制:開放 BeanFactoryPostProcessor、BeanPostProcessor 等擴展點。

??深入Spring源碼不僅能幫助解決實際開發中的復雜問題(如性能優化、定制化需求),還能提升對框架設計思想的理解,為開發高質量應用奠定基礎。

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

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

相關文章

如何簡單的去使用jconsloe 查看線程 (多線程編程篇1)

目錄 前言 1.進程和線程 進程 PCB 的作用 并發編程和并行編程 線程 為什么選擇多線程編程 2.在IDEA中如何簡單創建一個線程 1. 通過繼承Thread類 2. 通過實現 Runnable 接口 3. 使用 Lambda 表達式 3.如何簡單使用jconsloe去查看創建好的線程 前言 2025來了,這是第…

【ISO 14229-1:2023 UDS診斷(ECU復位0x11服務)測試用例CAPL代碼全解析④】

ISO 14229-1:2023 UDS診斷【ECU復位0x11服務】_TestCase04 作者&#xff1a;車端域控測試工程師 更新日期&#xff1a;2025年02月17日 關鍵詞&#xff1a;UDS診斷協議、ECU復位服務、0x11服務、ISO 14229-1:2023 TC11-004測試用例 用例ID測試場景驗證要點參考條款預期結果TC…

3.10 實戰Hugging Face Transformers:從文本分類到模型部署全流程

實戰Hugging Face Transformers:從文本分類到模型部署全流程 一、文本分類實戰:IMDB電影評論情感分析 1.1 數據準備與預處理 from datasets import load_dataset from transformers import AutoTokenizer # 加載IMDB數據集 dataset = load_dataset("imdb") …

【人工智能】釋放數據潛能:使用Featuretools進行自動化特征工程

《Python OpenCV從菜鳥到高手》帶你進入圖像處理與計算機視覺的大門! 解鎖Python編程的無限可能:《奇妙的Python》帶你漫游代碼世界 特征工程是機器學習流程中至關重要的一步,它直接影響模型的性能。然而,手動特征工程既耗時又需要領域專業知識。Featuretools是一個強大的…

MybaitsPlus學習筆記(二)基本CURD

目錄 一、BaseMapper 二、常用實例 1、插入 2、刪除 3、修改 4、查詢 三、IService 四、 IService中的一些方法測試 一、BaseMapper MyBatis-Plus中的基本CRUD在內置的BaseMapper中都已得到了實現&#xff0c;我們可以直接使用&#xff0c;接口如 下&#xff1a; publ…

設計模式之適配模式是什么?以及在Spring AOP中的攔截器鏈的使用源碼解析。

前言 本文涉及到適配模式的基本用法&#xff0c;以及在Spring AOP中如何使用&#xff0c;首先需要了解適配模式的工作原理&#xff0c;然后結合Spring AOP的具體實現來詳細詳細解析源碼。 首先&#xff0c;適配模式&#xff0c;也就是Adapter Pattern&#xff0c;屬于結構型設計…

【C++】36.C++IO流

文章目錄 1. C語言的輸入與輸出2. 流是什么3. CIO流3.1 C標準IO流3.2 C文件IO流 4. stringstream的簡單介紹 1. C語言的輸入與輸出 C語言中我們用到的最頻繁的輸入輸出方式就是scanf ()與printf()。 scanf(): 從標準輸入設備(鍵盤)讀取數據&#xff0c;并將值存放在變量中。pri…

JavaScript表單介紹

一、表單的基本概念 在網頁開發里&#xff0c;表單是實現用戶與網頁交互的關鍵組件&#xff0c;用于收集用戶輸入的數據&#xff0c;JavaScript 則能為表單增添強大的交互性和功能性。表單在 HTML 里通過 <form> 標簽創建&#xff0c;包含多種表單元素&#xff0c;如文本…

哈希表(C語言版)

文章目錄 哈希表原理實現(無自動擴容功能)代碼運行結果 分析應用 哈希表 如何統計一段文本中&#xff0c;小寫字母出現的次數? 顯然&#xff0c;我們可以用數組 int table[26] 來存儲每個小寫字母出現的次數&#xff0c;而且這樣處理&#xff0c;效率奇高。假如我們想知道字…

昆蟲-目標檢測數據集(包括VOC格式、YOLO格式)

昆蟲-目標檢測數據集&#xff08;包括VOC格式、YOLO格式&#xff09; 數據集&#xff1a; 鏈接: https://pan.baidu.com/s/1tYb8s-AVJgSp7SGvqdWF9A?pwdt76a 提取碼: t76a 數據集信息介紹&#xff1a; 共有 6009 張圖像和一一對應的標注文件 標注文件格式提供了兩種&#x…

C++(23):unreachable

C++23在頭文件 "><utility>定義了std::unreachable(),用于指示編譯器,該段代碼不應該被允許,因此編譯器可以對該位置進行優化,如果一旦允許了該位置的代碼,行為未定義: #include <utility> #include <iostream>using namespace std;int func(…

備戰藍橋杯 Day1 回顧語言基礎

開啟藍橋杯刷題之路 Day1 回顧語言基礎 1.配置dev 工具->編譯選項->勾選編譯時加入以下命令->設定編譯器配置(release和debug)都要-> -stdc11 ->代碼生成/優化->代碼生成/優化->語言標準(-std)->ISO C11 ->代碼警告->顯示最多警告信息(-Wall)…

python學opencv|讀取圖像(七十五)人臉識別:Fisherfaces算法和LBPH算法

【1】引言 前序學習進程中&#xff0c;已經掌握了使用Eigenfaces算法進行的人臉識別。相關文章鏈接為&#xff1a; python學opencv|讀取圖像&#xff08;七十四&#xff09;人臉識別&#xff1a;EigenFaces算法-CSDN博客 在此基礎上&#xff0c;學習剩余兩種人臉識別算法&am…

React 前端框架介紹

什么是 React&#xff1f; React 是一個由 Facebook 開發并維護的開源 JavaScript 庫&#xff0c;用于構建用戶界面。它主要用于創建交互式用戶界Face&#xff08;UI&#xff09;&#xff0c;尤其是當數據變化時需要更新部分視圖時非常有效。React 的核心思想是組件化和聲明性…

包裝類的空指針異常

問題&#xff1a; Integer是引用對象&#xff0c;當初始化不進行賦值的時候是null,是null就不可以自動拆箱 實踐&#xff1a; public class Test {public static void main(String[] args) {Integer num null;//自動拆箱int i num;} } 會包異常信息&#xff1a; Excepti…

【Elasticsearch】檢索選定字段(Retrieve selected fields)

在 Elasticsearch 中&#xff0c;檢索選定字段&#xff08;Retrieve selected fields&#xff09;是一個重要的功能&#xff0c;用于優化查詢性能和減少數據傳輸量。以下是結合所有回答的詳細總結&#xff0c;涵蓋每種字段檢索方式的原理、應用場景、性能特點以及限制。 1._so…

【MySQL】 基本查詢(下)

歡迎拜訪&#xff1a;霧里看山-CSDN博客 本篇主題&#xff1a;【MySQL】 基本查詢(下) 發布時間&#xff1a;2025.2.18 隸屬專欄&#xff1a;MySQL 目錄 Update語法案例 Delete刪除數據語法案例 截斷表語法案例 插入查詢結果語法案例 聚合函數函數介紹案例 group by子句的使用語…

docker 基礎命令使用(ubuntu)

docker 狀態查詢 docker ps docker ps -adocker --version docker info docker --help docker run --help docker ps --help ...docker 操作鏡像命令 docker imagesdocker rmi 鏡像id/鏡像名docker 操作容器命令 docker ps docker ps -adocker run 命令 # 端口映射 -p 參數…

idea 2023.3.7常用插件

idea 2023.3.7常用插件 文檔 idea 2019.3常用插件idea 2023.3.7常用插件 idea 2023.3.7常用插件 插件名稱插件版本說明1AceJump3.5.9AceJump允許您快速將插入符號導航到編輯器中可見的任何位置。只需按“ctrl&#xff1b;”&#xff0c;鍵入一個字符&#xff0c;然后在Ace …

基于Flask的廣西高校輿情分析系統的設計與實現

【Flask】基于Flask的廣西高校輿情分析系統的設計與實現&#xff08;完整系統源碼開發筆記詳細部署教程&#xff09;? 目錄 一、項目簡介二、項目界面展示三、項目視頻展示 一、項目簡介 該系統綜合運用Python、Flask框架及多種數據處理與可視化工具開發&#xff0c;結合Boot…