Spring源碼解析 - AbstractBeanFactory 實現接口與父類分析

咱們先來看類圖吧:android

除了BeanFactory這一支的接口,AbstractBeanFactory主要實現了AliasRegistry和SingletonBeanRegistry接口.web

這邊主要提供了這樣的三個功能: 別名管理,單例建立與註冊,工廠方法FactoryBean支持.spring

Spring源碼解析 - AbstractBeanFactory 實現接口與父類分析

咱們來看看這些接口,類的主要職責吧:設計模式

BeanFactory Spring IOC容器的根接口api

-- HierachicalBeanFactory 實現容器的繼承,就是能夠有父 BeanFactory緩存

-- -- ConfigureabelBeanFactory提供factory的配置功能安全

AliasRegistry 定義bean name的別名管理app

-- SimpleAliasRegistry 在實現別名管理接口基礎上,添加一個canonicalName查找類真是名稱api函數

SingletonBeanRegistry 提供單例註冊,查詢服務post

-- DefaultSingletonBeanRegistry 實現單例與DisposableBean的生命週期管理(建立,維護,銷燬)

-- --FactoryBeanRegistrySupport 添加工廠方式建立類FactoryBean的支持

-- -- -- AbstractBeanFactory BeanFactory的抽象實現.

也就是說這邊能夠分爲這樣幾類職責:

a, 類別名管理

b, 單例生命週期管理

c, 工廠方法初始化類對應的FactoryBean

d, BeanFactory容器

BeanFactory容器的職責(BeanFactory,HierachicalBeanFactory,ConfigureableBeanFactory)在上一篇文章<Spring源碼解析 - BeanFactory接口體系解讀>裏已經分析過,有興趣能夠看下.

咱們今天主要分析其餘的三個職責,以下的接口與類(順便作目錄):

1. AliasRegistry 定義bean name的別名管理

2. SimpleAliasRegistry 實現別名管理接口

3. SingletonBeanRegistry 提供單例註冊,查詢服務

4. DefaultSingletonBeanRegistry 實現單例與DisposableBean的生命週期管理(建立,維護,銷燬)

5. FactoryBeanRegistrySupport 添加工廠方式建立類FactoryBean的支持

1. AliasRegistry 定義bean name的別名管理

提供別名的註冊,查找,刪除,判判定義.

看個類圖就行,不用展開.

Spring源碼解析 - AbstractBeanFactory 實現接口與父類分析

2. SimpleAliasRegistry 實現別名管理接口

這邊除了實現接口定義的api,還添加了兩個公共api:

批量校驗別名public void resolveAliases(StringValueResolver valueResolver)和查找別名對應的原始類名public String canonicalName(String name)

這邊以別名爲key緩存數據.

1     /** Map from alias to canonical name */
2     private final Map<String, String> aliasMap = new ConcurrentHashMap<String, String>(16);

分析下api實現邏輯吧:

2.1 別名註冊 registerAlias(String name, String alias)

Spring源碼解析 - AbstractBeanFactory 實現接口與父類分析

2.2 刪除別名public void removeAlias(String alias)

校驗下,若是別名不存在報錯:throw new IllegalStateException("No alias '" + alias + "' registered");

2.3 判斷別名是否存在

直接使用ConcurrentHashMap的containsKey

2.4 獲取別名public String getAliases(String name)

主要邏輯是加了個鎖,而後是遞歸調用retrieveAliases,查找多層次的別名(就是查找別名的別名這些下去)

2.5 使用StringValueResolver解析類名,別名後,進行循環依賴的校驗

這邊使用的是StringValueResolver的接口,具體實現須要靠注入

3. SingletonBeanRegistry 提供單例註冊,查詢服務

這邊定義的單例註冊,有點門道,主要就是相對BeanFactory的api而言有點low,沒有作附加的處理.

註冊的時候無論注入afterPropertiesSet的初始化回調.

查找的時候無論還沒初始化的單例不說,還無論別名問題,無論FactoryBean如何區分是獲取FactoryBean自己仍是getObject初始化的實例.

我們一個個api分析吧.

3.1 註冊單例 void registerSingleton(String beanName, Object singletonObject);

這邊的實現不會再調用 初始化回調函數,如InitializingBean的afterPropertiesSet,因此這邊應該接收的是完成初始化的實例

同理也不會調用銷燬的回調,如DisposableBean的destroy

這跟標準的BeanFactory中註冊單例是明顯不一樣的,由於那邊是會調用各類回調.

3.2 查找單例Object getSingleton(String beanName);

String getSingletonNames;

int getSingletonCount;

設計於訪問手動註冊的單例.

這邊只會查找已經初始化完畢 的單例,有bean definition但沒有實例化的這邊查找不到.

這邊也不會處理FactoryBean的狀況(就是具體獲取getObject仍是factoryBean自己的區分,&),別名也須要預先轉化好了來查.

3.3 判斷是否保護單例boolean containsSingleton(String beanName);

只有單例已經實例化纔會返回true,剩下的看3.2 查找單例的說明吧,同樣的.

4. DefaultSingletonBeanRegistry 實現單例與DisposableBean的生命週期管理(建立,維護,銷燬)

在SingletonBeanRegistry註冊的基礎上,添加單例的共享.

也支持容器關閉時,DisposableBean實例的銷燬

4.1 這邊註冊時,經過下面四個變量來維護:

Map<String, Object> singletonObjects 緩存以bean name爲key的單例實例

Map<String, ObjectFactory> singletonFactories 緩存以bean name 爲key的ObjectFactory

Map<String, Object> earlySingletonObjects 用於解決單例時的循環依賴,這邊緩存以bean name爲key的預初始化單例

Set<String> registeredSingletons 已經註冊好的單例bean name

這邊singletonObjects和registeredSingletons的數據應該是同步的,只是適用於不一樣的場景,但他們倆跟singletonFactories 和earlySingletonObjects分別互斥,就是singletonObjects裏有了,這兩個確定沒有.

同時這邊也有inCreationCheckExclusions和singletonsCurrentlyInCreation進行鎖控制的概念.

singletonsCurrentlyInCreation緩存bean正在被初始化,這樣就不能再發起初始化;

inCreationCheckExclusions 直接緩存當前不能加載的bean

這部分看個例子就,清晰了,初始化前須要先使用beforeSingletonCreation判斷

這邊inCreationCheckExclusions不包含beanName纔會去判斷singletonsCurrentlyInCreation

1     protected void beforeSingletonCreation(String beanName) {
2         if (!this.inCreationCheckExclusions.containsKey(beanName) &&
3 this.singletonsCurrentlyInCreation.put(beanName, Boolean.TRUE) != null) {
4 throw new BeanCurrentlyInCreationException(beanName);
5         }
6     }

4.2 管理bean的依賴問題

使用以下三個屬性進行管理:

Map<String, Set<String>> containedBeanMap 依賴的bean name爲key , 就是依賴類 -> 查找 被依賴的類

Map<String, Set<String>> dependentBeanMap 依賴的原始bean name爲key

Map<String, Set<String>> dependenciesForBeanMap 被依賴的bean name爲key

4.3 bean 銷燬

這不過跟初始化相似,自行看代碼比較簡單.

5. FactoryBeanRegistrySupport 添加工廠方式建立類FactoryBean的支持

添加對FactoryBean的支持,就是使用工廠方法初始化類.

這裏主要涉及3個新概念:FactoryBean,BeanPostProcessor和AccessController.這三個概念懂了,源碼也就分析完了.

5.1 FactoryBean,經過T getObject api提供簡單工廠方法,可用用於建立單例,原型模式的實例.主要用於建立過程複雜,xml配置不方便的狀況.

其實這個就是使用spring的接口對簡單工廠設計模式作了一個規範,方便你們在spring中配置使用.

5.2BeanPostProcessor用於bean 初始化時進行功能加強,相似web開發中的filter.

這邊有兩個api:

postProcessBeforeInitialization 在類初始化前調用,比InitializaingBean 的 setPropertiesSet 和 xml文件中自定義的init-method方法執行都早

postProcessAfterInitialization 類初始話後調用,在InitializaingBean 的 setPropertiesSet 和 xml文件中自定義的init-method方法以後執行

5.3AccessController jdk的安全控制,跟spring關聯不大,仍是度娘吧,很少寫了.

在 Java 中將執行程序分紅本地和遠程兩種,本地代碼默認視爲可信任的,而遠程代碼則被看做是不受信的。對於授信的本地代碼,能夠訪問一切本地資源。

在應用開發中還有一些關於安全的複雜用法,其中最經常使用到的 API 就是 doPrivileged。doPrivileged 方法可以使一段受信任代碼得到更大的權限,甚至比調用它的應用程序還要多,可作到臨時訪問更多的資源。

因此就出現了spring中的典型代碼

 1 if (System.getSecurityManager != null) {
 2     AccessControlContext acc = getAccessControlContext;
 3     try {
 4         object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object> {
 5 public Object run throws Exception {
 6 return factory.getObject;
 7  }
 8  }, acc);
 9     }
10     catch (PrivilegedActionException pae) {
11         throw pae.getException;
12     }
13 }else {
14     object = factory.getObject;
15 }



轉自:http://toutiao.com/i6260723294287168002/?tt_from=mobile_qq&utm_campaign=client_share&app=news_article&utm_source=mobile_qq&iid=3796824860&utm_medium=toutiao_android

相關文章
相關標籤/搜索