說到spring不得不提其兩大特性IOC、AOP,本文主要介紹結合代碼看下spring Ioc相關原理,閱讀源碼若是隻是爲了看源碼效率就會很低,仍是要有必定的目的性,咱們結合着如下的問題去源碼中找答案。本篇文章爲《圖靈學院》課程筆記java
以下圖spring Ioc的總體架構圖中能夠看出,Spring啓動時讀取bean配置信息,並在spring中生成一份相應bean配置註冊表,而後會根據註冊表實例化Bean,而且裝配好bean 之間的依賴關係,爲上層應用提供bean實例,其中bean的緩存池是經過hashmap實現的git
spring.xml中保存了Bean的描述配置,BeanFactory讀取這些配置而後生成bean,這是咱們對ioc原理的通常理解,深刻思考還會有更多問題產生web
ioc 實現中 咱們在xml 中描述的Bean信息最後 都將保存至BeanDefinition (定義)對象中,其中xml bean 與BeanDefinition 程一對一的關係。xml bean中設置的屬性最後都會體如今BeanDefinition中spring
因而可知,xml bean中設置的屬性最後都會體如今BeanDefinition中。如:緩存
**XML-bean ** | BeanDefinition |
---|---|
class | beanClassName |
scope | scope |
lazy-init | lazyInit |
constructor-arg | ConstructorArgument |
property | MutablePropertyValues |
factory-method | factoryMethodName |
destroy-method | AbstractBeanDefinition.destroyMethodName |
init-method | AbstractBeanDefinition.initMethodName |
autowire | AbstractBeanDefinition.autowireMode |
id | |
name |
在上表中咱們並無看到 xml bean 中的 id 和name屬性沒有體如今定義中,緣由是ID 其做爲當前Bean的存儲key註冊到了BeanDefinitionRegistry 註冊器中。name 做爲別名key 註冊到了 AliasRegistry 註冊中心。其最後都是指向其對應的BeanDefinition。markdown
BeanDefinitionRegistry屬性結構架構
BeanDefinitionReader(Bean定義讀取)oop
如今咱們瞭解 BeanDefinition 中存儲了Xml Bean信息,而BeanDefinitionRegister 基於ID和name 保存了Bean的定義。接下要學習的是從xml Bean到BeanDefinition 而後在註冊至BeanDefinitionRegister 整個過程。學習
上圖中能夠看出Bean的定義是由BeanDefinitionReader 從xml 中讀取配置並構建出 BeanDefinitionReader,而後在基於別名註冊到BeanDefinitionRegister中。ui
BeanDefinitionReader結構
基於資源加載beanDefinition並註冊到註冊器
int loadBeanDefinitions(String var1)
基於資源路徑加載beanDefinition並註冊大屏註冊器
BeanDefinitionRegistry getRegistry()
獲取註冊器
ResourceLoader getResourceLoader()
獲取資源裝載器
//建立一個簡單註冊器
BeanDefinitionRegistry register = new SimpleBeanDefinitionRegistry();
//建立bean定義讀取器
BeanDefinitionReader reader = new XmlBeanDefinitionReader(register);
// 建立資源讀取器
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
// 獲取資源
Resource xmlResource = resourceLoader.getResource("spring.xml");
// 裝載Bean的定義
reader.loadBeanDefinitions(xmlResource);
// 打印構建的Bean 名稱
System.out.println(Arrays.toString(register.getBeanDefinitionNames());
複製代碼
有了Bean的定義就至關於有了產品的配方,接下來就是要把這個配方送到工廠進行生產了。在ioc當中Bean的構建是由BeanFactory 負責的。其結構以下:
方法說明:
以上方法中重點要關注getBean,當用戶調用getBean的時候就會觸發 Bean的建立動做,其是如何建立的呢?
#建立Bean堆棧
// 其反射實例化Bean
java.lang.reflect.Constructor.newInstance(Unknown Source:-1)
BeanUtils.instantiateClass()
//基於實例化策略 實例化Bean
SimpleInstantiationStrategy.instantiate()
AbstractAutowireCapableBeanFactory.instantiateBean()
// 執行Bean的實例化方法
AbstractAutowireCapableBeanFactory.createBeanInstance()
AbstractAutowireCapableBeanFactory.doCreateBean()
// 執行Bean的建立
AbstractAutowireCapableBeanFactory.createBean()
// 緩存中沒有,調用指定Bean工廠建立Bean
AbstractBeanFactory$1.getObject()
// 從單例註冊中心獲取Bean緩存
DefaultSingletonBeanRegistry.getSingleton()
AbstractBeanFactory.doGetBean()
// 獲取Bean
AbstractBeanFactory.getBean()
// 調用的客戶類
com.tuling.spring.BeanFactoryExample.main()
複製代碼
Bean建立時序圖:
從調用過程能夠總結出如下幾點:
BeanFactory 看上去能夠去作IOC當中的大部分事情,爲何還要去定義一個ApplicationContext 呢? ApplicationContext 結構圖
從圖中能夠看到 ApplicationContext 它由BeanFactory接口派生而來,於是提供了BeanFactory全部的功能。除此以外context包還提供瞭如下的功能:
原文地址