1. 程式人生 > >spring容器及bean載入機制原始碼解讀

spring容器及bean載入機制原始碼解讀

前言:這是本人第一個部落格,早就想記錄些總結和理解,可一直不知道從哪開始,最近正好在解決一個spring的問題,正好這個問題涉及到了spring的一些相關基礎,整理一下就從這部分開始了。
歡迎所有閱讀者和愛好者批評從各個方面(特別是文件和技術方面)批評,指正。互相交流學習。
原想這部分單寫一個文章可無奈文筆有限,先放在這吧。

spring的容器載入機制分為提前載入和執行時動態載入,本文通過原始碼解讀容器載入機制和bean載入機制。
1、spring 啟動的時候載入
這裡寫圖片描述
(圖1.1)
obtainFreshBeanFactory方法中實現了beanFactory的初始化和對配置檔案、註解載入。
registerBeanPostProcessors(beanFactory); 方法實現了註冊bean自定義初始化(不是類物件例項化)前後的處理器的註冊資訊。
finishBeanFactoryInitialization 方法是處理提前載入的哪些例項
1.1 spring的配置是怎麼樣讀取的都幹了什麼
由於篇幅較大這部分使用單獨篇幅:

http://blog.csdn.net/songyang19871115/article/details/54346444

1.2 spring都提前載入了哪些自帶和自定義的bean
這裡寫圖片描述
(圖1.2.1)
這裡寫圖片描述
(圖1.2.2)

如以上程式碼(圖1.2.1,圖1.2.2):應用上下文在啟動的時候會自動呼叫這段程式碼,這段程式碼會初始化所有(非懶載入的、單例的、不是抽象的 bean或者SmartFactoryBean)
這裡使用了beanDefinitionNames這個集合,這個集合是從配置檔案和註解中獲取出來的,所有bean的名稱。來實現bean的提前載入。

至此 與spring一般的初始化bean,bean工廠,bean 的初始化前置執行器都已經執行完了。

2、spring 動態載入的實現
spring的一切都是為了bean不論是自定義的還是spring自帶的,而bean是怎麼來的,是什麼樣的bean都是從getBean開始的,下面揭開他的神祕面紗:
2.1doGetBean的實現:
這裡寫圖片描述
(圖2.1.1)
這裡寫圖片描述
(圖2.1.2)
這裡寫圖片描述
(圖2.1.3)
(圖2.1.1,2.1.2,2.1.3為doGetBean的程式碼實現)
1、如果是單例看看是否在當前容器中。如果單例快取中沒有則檢視父容器有沒有同名的bean,如果有則返回。說明如果子容器沒有這個bean,會從父容器中獲取,直到祖先容器都沒有。
getObjectForBeanInstance 只是處理如果當前bean是工廠bean的情況
2、獲取bean的定義描述資訊,如果存在依賴按個遞迴呼叫getBean獲取依賴的bean,並且註冊到當前的bean上
3、如果當前容器和祖先容器都沒有則開始建立bean 例項
4、處理bean的轉換問題,spring自帶conversionService
2.2 createBean的原始碼實現:
這裡寫圖片描述


(圖2.2.1)
這裡寫圖片描述
(圖2.2.2)
這裡寫圖片描述
(圖2.2.3)
從原始碼得知,只有bean在建立以前都做了什麼,先是檢視這個容器中是否含有beanPostProcessors()(這個是由refresh方法呼叫registerBeanPostProcessors()時候註冊進去的)
並且是InstantiationAwareBeanPostProcessor 介面的實現類,如果bean提前實現了,呼叫beanPostProcessors 的 postProcessAfterInitialization 將用不在呼叫doCreateBean方法(具體實現如圖2.2.2,2.2.3).這塊也體現了spring的靈活,連bean的建立都可以定製。

下面說下doCreateBean的建立原理和執行內幕:
這裡寫圖片描述
(圖2.2.4)
這裡寫圖片描述
(圖2.2.5)
圖2.2.4和2.2.5是doCreateBean的實現細節
createBeanInstance中實現了bean的例項的過程,其中包含了構造方法,工廠方法的例項並且放置在beanWrapperImpl中。
populateBean中實現了bean的屬性的注入,其中區分了屬性的強校驗注入等,而且遞迴呼叫getBean方法。
registerDisposableBeanIfNecessary 為當前bean的銷燬提供策略和實現
initializeBean中的實現下面會詳細闡述。

下面詳細說下initializeBean方法
這裡寫圖片描述
(圖2.2.6)
這個方法並不是物件例項的方法,而是物件例項後的方法。
invokeAwareMethod方法是如果當前的bean是BeanNameAware,BeanClassLoaderAware,BeanFactoryAware 建立bean的時候,會幫你把你需要的資料放進去,但前提一定是三個介面的實現類。
applyBeanPostProcessorsBeforeInitialization 會呼叫當前容器中所有的BeanPostProcessor 並且執行他們的postProcessBeforeInitialization 方法
invokeInitMethods 是先呼叫bean的afterPropertiesSet 前提bean是InitializingBean的實現類,然後呼叫bean 的 initMethod
applyBeanPostProcessorsAfterInitialization 會呼叫當前容器中所有的BeanPostProcessor 並且執行他們的postProcessAfterInitialization 方法 (這個方法為以後理解代理的相關原理及實現方式埋下伏筆)

至此 springIOC 最核心的提前載入和執行時獲取並載入的主要功能及原始碼解析說完了。 其他的功能請按這個順序也可不按看原始碼找到答案,但spring 程式碼非常龐大並且複雜設計模式用的非常廣泛,最好看的抓住核心才能避免事倍功半。
個人理解,雖然有時原理或者實現機制看樣子並不能解決碰到的非常複雜問題,但是會為以後解決各種問題及二次開發,打好基本功。

相關推薦

spring容器bean載入機制原始碼解讀

前言:這是本人第一個部落格,早就想記錄些總結和理解,可一直不知道從哪開始,最近正好在解決一個spring的問題,正好這個問題涉及到了spring的一些相關基礎,整理一下就從這部分開始了。 歡迎所有閱讀者和愛好者批評從各個方面(特別是文件和技術方面)批評,指正。

Spring FrameWork的bean載入機制

其實原始碼是個好東西,好到讓你理解作者的初心和想法是如何一步步實現的,例如spring,我們更習慣於拿來當應用去使用,但適當的去研究下原始碼的實現就會掌握很多幹貨。 千萬言不抵一書,梳理下spring的

JDK類載入機制原始碼分析原始碼分析

JVM的類載入機制主要有如下三種機制: 1.全盤負責:所謂全盤負責,就是說當一個類載入器載入個個Class的時候,該Class所依賴和引用的其他Class也將由該類載入 器負責載入,除非使用另外一個類載入器來載入。 2.雙親委託:所謂雙親委託則是先讓parent(父)類載入器

三、獲取Spring容器獲取容器中的Bean物件

  Spring中的容器物件介面是ApplicationContext,其作用就是載入配置檔案,並初始化所有的Bean物件(容器啟動時)。其實現類主要有2個,分別為: ClassPathXmlApplicationContext:載入類路徑下的Spring

Spring--IOCBean容器

介面: 面向介面程式設計: IOC: eg: 單元測試: Bean容器初始化: 初始化ApplicationContext的方式: 載入本地檔案,指定到具體的磁碟目錄的檔案 Classpath:相對路徑,相

半夜思考之查漏補缺 , Spring 中的 Bean 繼承機制

size 完全 font 區別 nbsp spring 多態 實例 ont 這裏的繼承 , 不是 Java 中的繼承 , 下面就總結下 Bean繼承與Java繼承的區別: Spring 中的子類 Bean 和父 Bean 可以是不同類型 , 但是 Java

Spring容器bean概要

com init 管理 pass XML efi AC pre color 容器:   通俗的理解容器就是用來管理bean和bean之間依賴的一個組件。很多參考資料說容器就是org.springframework.context.ApplicationContext,但筆者

Spring容器Bean的生命周期

pub run down xsd 信息 ini exc rop throw Spring生命周期分為以下步驟: 1.instantiate bean 對象實例化 2.populate properties 封裝屬性 3.如果Bean實現BeanNameAware執行setB

普通Java類獲取spring 容器bean的5種方法 Spring注入非單例bean以及scope的作用範圍

本文轉載自:http://www.cnblogs.com/duanxz/archive/2014/06/18/3794075.html 方法一:在初始化時儲存ApplicationContext物件方法二:通過Spring提供的工具類獲取ApplicationContext物件方法三:繼承自抽象類Appli

filter中使用Spring容器注入bean

[1] XML配置形式 Tomcat容器初始化順序:監聽器–>過濾器–>servlet,因此springMVCservlet初始化之前,過濾器就已經初始化過了,如果在過濾器中需要注入spring容器管理的bean是注入不進去的,因此需要在spring監聽器中初始化需要注入的bean,

實現ApplicationContextAware介面,java(new或者java反射獲取的物件)中獲取spring容器bean

本文參考了https://blog.csdn.net/bailinbbc/article/details/76446594,其實是拷貝了很多內容: 在Web應用中,Spring容器通常採用宣告式方式配置產生:開發者只要在web.xml中配置一個Listener,該Listener將會負責初始化S

4. IOC容器的依賴注入(原始碼解讀

一、基本概念 1.當Spring IoC容器完成了Bean定義資源的定位、載入和解析註冊以後,IoC容器中已經管理類Bean定義的相關資料,但是此時IoC容器還沒有對所管理的Bean進行依賴注入,依賴注入在以下兩種情況發生: (1)使用者第一次通過getBean

Spring容器bean的注入(1)

第一節 在IOC容器中裝配Bean 1.1Spring容器成功啟動條件 1.匯入Spring框架相關的jar包 2.正確配置spring配置檔案 3.Bean的類都已放到應用程式的類路徑下 1.2Bean配置資訊的組成 Bean配置資

spring容器建立bean物件的方式

1)xml檔案中有bean的配置,而且這個bean所對應的java類中存在一個無參構造器,那麼這個時候spring容器就可以使用反射呼叫無參構造器來建立例項了(常規的方式) 2)通過工廠類獲得例項(工廠類實現了介面FactoryBean<?>) 例如: xml中的配置

Spring學習筆記一(Spring容器bean的注入)

第一節 在IOC容器中裝配Bean 1.1Spring容器成功啟動條件 1.匯入Spring框架相關的jar包 2.正確配置spring配置檔案 3.Bean的類都已放到應用程式的類路徑下 1.2Bean配置資訊的組成 Bean配置資訊是Bean的元資料資訊(

spring容器的懶載入

預設情況下,spring的IOC容器中lazy-init是false的,即沒有開啟懶載入模式。 如果你沒有看到這個lazy-init 的引數設定就說明是false啦。 那麼什麼是懶載入? 懶載入---就是我們在spring容器啟動的是先不把所有的bean都載入到

Spring容器啟動 Bean的3種初始化方式

通常我們建立一個Bean的時候,可能有這樣的需求,比如我建立了一個連線資料庫的Bean類,我希望在Spring容器建立的時候,就檢查下是否能正常訪問資料庫。這時候我們可以藉助於以下方式進行實現。1、如果

Spring容器Bean的生命週期(init-method destroy-method)

Spring容器中Bean的生命週期 這一篇很詳細的講了Bean生命週期的每一個過程。     我主要是想實現一下init方法核destory方法,因為這個和AOP程式設計的環繞通知有點兒相似的感覺,所以特別來研究一下這兩個方法。      在Spring配置中,i

Composer自動載入機制原始碼剖析

1、autoload.php 要使用Composer的自動載入,首先需要引入該檔案 <?php // autoload.php @generated by Composer // 引入au

java 如何在listener(監聽器) 中使用Spring容器管理bean

問題來源:在Listener監聽器中無法使用Spring容器的@Resource或者@Autowired 註解的方法注入bean,因為,在web Server容器中,無論是Servlet,Filter,還是Listener都不是Spring容器管理的,因此我們都無法在這些