Spring IOC原理

說到spring不得不提其兩大特性IOC、AOP,本文主要介紹結合代碼看下spring Ioc相關原理,閱讀源碼若是隻是爲了看源碼效率就會很低,仍是要有必定的目的性,咱們結合着如下的問題去源碼中找答案。本篇文章爲《圖靈學院》課程筆記java

  • Bean工廠是如何產生Bean的
  • Bean的依賴關係是由誰來解決的
  • Bean工廠和應用上下文的區別

以下圖spring Ioc的總體架構圖中能夠看出,Spring啓動時讀取bean配置信息,並在spring中生成一份相應bean配置註冊表,而後會根據註冊表實例化Bean,而且裝配好bean 之間的依賴關係,爲上層應用提供bean實例,其中bean的緩存池是經過hashmap實現的git

bean的構建過程

spring.xml中保存了Bean的描述配置,BeanFactory讀取這些配置而後生成bean,這是咱們對ioc原理的通常理解,深刻思考還會有更多問題產生web

  • 哪一個java對象承載了配置信息裏的內容
  • 這些承載對象是讀取配置文件並裝載的
  • 這些裝載對象又保存在哪裏

BeanDefinition(Bean定義)

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

BeanDefinition 屬性結構

BeanDefinitionRegistry(Bean註冊器)

在上表中咱們並無看到 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結構

  • int loadBeanDefinitions(Resource var1)

基於資源加載beanDefinition並註冊到註冊器

  • int loadBeanDefinitions(String var1)

    基於資源路徑加載beanDefinition並註冊大屏註冊器

  • BeanDefinitionRegistry getRegistry()

    獲取註冊器

  • ResourceLoader getResourceLoader()

獲取資源裝載器

基於示例演示BeanDefinitionReader裝載過程

//建立一個簡單註冊器
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());
複製代碼

Beanfactory(bean 工廠)

有了Bean的定義就至關於有了產品的配方,接下來就是要把這個配方送到工廠進行生產了。在ioc當中Bean的構建是由BeanFactory 負責的。其結構以下:

方法說明:

  • getBean(String)
    • 基於ID或name 獲取一個Bean
  • T getBean(Class requiredType) 
    • 基於Bean的類別獲取一個Bean(若是出現多個該類的實例,將會報錯。但能夠指定 primary=「true」 調整優先級來解決該錯誤 )
  • Object getBean(String name, Object... args)
    • 基於名稱獲取一個Bean,並覆蓋默認的構造參數
  • boolean isTypeMatch(String name, Class<?> typeToMatch)
    • 指定Bean與指定Class 是否匹配

以上方法中重點要關注getBean,當用戶調用getBean的時候就會觸發 Bean的建立動做,其是如何建立的呢?

演示基本BeanFactory獲取一個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建立時序圖:

從調用過程能夠總結出如下幾點:

  1. 調用BeanFactory.getBean() 會觸發Bean的實例化。
  2. DefaultSingletonBeanRegistry 中緩存了單例Bean
  3. Bean的建立與初始化是由AbstractAutowireCapableBeanFactory 完成的。

BeanFactory 與 ApplicationContext區別

BeanFactory 看上去能夠去作IOC當中的大部分事情,爲何還要去定義一個ApplicationContext 呢? ApplicationContext 結構圖

從圖中能夠看到 ApplicationContext 它由BeanFactory接口派生而來,於是提供了BeanFactory全部的功能。除此以外context包還提供瞭如下的功能:

  1. MessageSource, 提供國際化的消息訪問
  2. 資源訪問,如URL和文件
  3. 事件傳播,實現了ApplicationListener接口的bean
  4. 載入多個(有繼承關係)上下文 ,使得每個上下文都專一於一個特定的層次,好比應用的web層

原文地址

cbaj.gitee.io/blog/2020/0…

相關文章
相關標籤/搜索