1. 程式人生 > >Spring獲取Bean 原始碼淺析

Spring獲取Bean 原始碼淺析

今天開門見山,直接亮程式碼~

MyTestBean bean = (MyTestBean)bf.getBean("myTestBean")
我想上面這行程式碼,第一次接觸過spring這個框架時都應該接觸過;讀取xml中我們配置的bean;

spring分為7大部分組成,有一個部分叫做:SpringBean;

為了知道這句程式碼實現了什麼樣的功能,看官可以可以開啟你的開發工具,找到下面這張圖的幾個包;

首先開啟AbstractBeanFactory 這個類, 找到 getBean 這個方法:

public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}
進入doGetBean :
@SuppressWarnings("unchecked")
	protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {
//beanName 前面可能存在的 所有符號 全部取出;
		final String beanName = transformedBeanName(name);
		Object bean;

		/**
 * spring會先檢查快取中或者例項工廠中是否有對應的例項,因為在建立單例bean的時候回存在醫療注入的情況;
  * 而在建立以來的時候為了避免迴圈依賴,spring建立bean的原則是不等bean建立完成就會將建立bean的 objectfactory提前曝光,
 * 也就是將objectFactory加入到快取中,一旦下一個bean建立的時候需要依賴上個bean則直接使用objectfactory; 
 */
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isDebugEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

迴圈依賴是什麼意思呢?  如果存在 A中有B的屬性,B中又有A的屬性,那麼當依賴注入的時候,就會產生A還未完成建立的時候又去建立B,又再次返回建立A;

進入   getSingleton(beanName) 方法 會跳到 DefaultSingletonBeanRegistry 這個類的


再次進入 getSingleton(beanName, true )這個方法;

進入這個方法之前,先了解一個概念,單例在spring的同一個容器中只會被建立一個,之後獲取bean就可以直接衝單例的快取中獲取了;

下面介紹的就是從快取中獲取bean的情況;


這樣就返回了單例的 singletonObject

看到這裡,你可能不知道 singletonFactory怎麼來的, 進入  singletonFactories 這個 引用去看看:

/** Cache of singleton objects: bean name --> bean instance */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);

	/** Cache of singleton factories: bean name --> ObjectFactory */
	private final Map<String, ObjectFactory> singletonFactories = new HashMap<String, ObjectFactory>(16);

	/** Cache of early singleton objects: bean name --> bean instance */
	private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

	/** Set of registered singletons, containing the bean names in registration order */
	private final Set<String> registeredSingletons = new LinkedHashSet<String>(64);

1.singletonObjects : 用於儲存beanName和建立bean例項之間的關係 
2.singletonFactories : 用於儲存beanName和建立bean的工廠之間的關係 
3.earlySingletonObjects :也是儲存beanName和bean例項之間的關係,與singletonObjects 的不同之處在於,當一個單例bean被放在這裡後,那麼當bean還在建立過程中,就可以通過getBean的方法獲取了,其目的是用來檢測迴圈引用。 
4.registeredSingletons : 用於儲存當前所有已註冊的bean。

因為 singletonFactory實現了 ObjectFactory這個介面; spring全家桶 會根據 beanName去建立 一個singletonFactory;

上面是從緩衝中獲取單例,那麼緩衝中要是不存在已經載入好的單例bean,那就要重頭開始執行載入bean了,spring重寫了getSingleton,

public Object getSingleton ( String beanName, ObjectFactory singletonFactory) {  ......    }


從上面程式碼可以看到,spring依賴注入時,使用了雙重判斷加鎖的單例模式,首先從快取中獲取bean例項,如果為null,對快取map加鎖,然後再從快取中獲取bean,如果繼續為null,就建立一個bean。這樣雙重判斷,能夠避免在加鎖的瞬間,有其他依賴注入引發bean例項的建立,從而造成重複建立的結果。

Spring並沒有使用我們常見的私有構造方法來建立bean,而是通過singletonFactory.getObject()返回具體beanName對應的ObjectFactory來建立bean。

這就是spring獲取bean的一個簡單流程;建立了spring的bean物件,還沒完,還沒有例項化這個bean。 且聽下回分解~

相關推薦

Spring獲取Bean 原始碼淺析

今天開門見山,直接亮程式碼~ MyTestBean bean = (MyTestBean)bf.getBean("myTestBean")我想上面這行程式碼,第一次接觸過spring這個框架時都應該接觸過;讀取xml中我們配置的bean; spring分為7大部分組成,

IOC容器從BeanFactory獲取Bean原始碼淺析

我們經常說IOC容器,它具體由誰來充當這個角色呢,我的理解ApplicationContext是用來管理IOC容器中的Bean的,IOC容器本質上是由DefaultListableBeanFactory擔當的。我們想從容器中獲得某個Bean,是通過ApplicationCon

Spring獲取bean的一種方式

ext bean 使用 set implement tex spring ati ride 隨便一百度,網上一大把,並且還不止一種。所以這裏就只記錄目前用的一種好了。 實現ApplicationContextAware接口 即可: import org.springfra

Spring 獲取bean 幾種方式

讀取 獲取 static ava ade beans java ride .html 轉載自: http://www.cnblogs.com/luoluoshidafu/p/5659574.html 1.讀取xml文件的方式,這種在初學入門的時候比較適用 。     A

spring 獲取bean幾種方式

這種方式適合於採用Spring框架的B/S系統,通過ServletContext物件獲取ApplicationContext物件,然後在通過它獲取需要的類例項。 這個類提供了方便的功能,這樣你就不必去記 ServletContext 中屬性的名字。 它的getWebApplicationContext() 

Spring獲取bean幾種方式

方法四:繼承自抽象類WebApplicationObjectSupport 說明:類似上面方法,呼叫getWebApplicationContext()獲取WebApplicationContext 方法五:實現介面ApplicationContextAware 說明:實現該介面的setAppl

spring獲取bean例項(七)

Spring中獲取bean物件例項(七) 今天進行下面重要分析,從上一章我們可以得知,getSingleton最終的獲取物件還是呼叫createBean方法 sharedInstance = getSingleton(beanName, () -> { try

Spring獲取bean的三種方式

Demo 類程式碼: springbean xml 配置程式碼: 測試類程式碼: spring 獲取bean 第一種方法 BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("s

spring獲取bean的幾種方式

使用jdk:1.8、maven:3.3.3 spring獲取Bean的方式 pom.xml檔案內容: <?xml v

Spring原始碼:從FactoryBean獲取Bean的例項

主程式碼 詳細分析 主程式碼 類AbstractBeanFactory protected <T> T doGetBean(......){

static關鍵字,引發的spring普通類獲取springbean的思考

pan conf ati ets 普通 blog 編譯器 自定義 這也 在c++和java中static關鍵字用於修飾靜態成員變量和成員函數 舉例一個普通的javabean class AA { int a; static int b; geta/set

Spring在代碼中獲取bean的幾種方式(轉)

mxml get text spa 回調 獲取對象 ati -s null 獲取spring中bean的方式總結: 方法一:在初始化時保存ApplicationContext對象 1 ApplicationContext ac = new FileSystemXml

Spring Boot 獲取Bean對象實體

oid cep clas ride ext @override pub tex creat 一、實現 ApplicationContextAware 接口 package com.zxguan; import org.springframework.beans.Bean

springbean週期中BeanPostProcessor淺析

參考:https://www.cnblogs.com/sishang/p/6576665.html 1. 基本概念 spring容器在例項化bean之後(通過構造器建立物件並注入屬性值即為例項化),可以使用BeanPostProcessor介面在bean的初始化方法前後根據需要做自己的邏

Spring(4) Bean獲取Spring容器

當一個bean需要獲取它所在spring容器的時候,實際上這種情況是很常見的,例如要輸出國際化資訊,釋出事件等。 bean可以通過實現BeanFactoryAware介面實現獲取它所在的spring容器,BeanFactoryAware只有一個setBeanFactory方法,sprin

Springbean 註冊的原始碼解析

前言 所謂 bean 的註冊,就是把在配置檔案中配置的 <bean> 節點載入配記憶體中,供後續使用。 bean的註冊主要分為兩個階段,一個是準備階段,就是對配置檔案進行解析,把配置檔案載入到記憶體中,以 Document 的形式存放;第二個階段是對 Document 進行操作,獲取其中的節

Spring事務實現原始碼之事務實現以及Connection的繫結與獲取

PlatformTransactionManager是spring事務的高階抽象,事務的實現需要藉助PlatformTransactionManager完成,該管理主要方法如下: 當我們在使用事務的時候,需要呼叫如下方法獲取一個事務狀態物件。 TransactionS

Spring載入bean定義流程原始碼解析

在本文中,先對Spring載入和建立bean例項的流程跟著原始碼走一遍,在後續的文章中再對所涉及的類的其他方法具體介紹。 //這一步是載入指定的配置檔案 Resource resource = new ClassPathResource("bean.xm

spring 根據beanName獲取bean物件,呼叫其方法

通用類 @Component public class SpringContextUtil implements ApplicationContextAware { private static ApplicationContext applicationConte

[轉]結合原始碼淺析Struts2與Spring整合的原理

文章的結構如下: 一、回顧Struts2與Spring整合的配置方法 二、(重點)對關鍵配置的分析 -------------------------------------------------------- 一、回顧Struts2與Spring整合的配置