Spring框架之beans源碼徹底解析

導讀:Spring能夠說是Java企業開發裏最重要的技術。而Spring兩大核心IOC(Inversion of Control控制反轉)和AOP(Aspect Oriented Programming面向切面編程)其中又以IOC最爲核心。IOC容器是Spring的核心模塊,Spring提供了兩種類型的容器,一個是BeanFactory,一個是ApplicationContext,而ApplicationContext是BeanFactory擴展來的。java

本文就Spring框架的beans源碼進行解析,主要從如下幾個方面進行:一是Spring框架介紹,對Spring總體架構有個直觀的瞭解;二是對beans源碼文件清單進行梳理,共12大類,257個java文件,對DefaultListableBeanFactory等一些核心類進行了重點分析;三是對BeanDefinition進行解析,BeanDefinition 在 spring 中貫穿始終,是spring 一塊基石;四是對Bean默認標籤解析全過程進行了分析;五是以doGetBean函數爲核心,分析Bean的加載過程;六是介紹ApplicationContext和BeanFactory兩種容器的Bean的生命週期。node


文章目錄
web

1、Spring框架簡介算法

2、Beans源碼文件清單spring

  一、  org.springframework.beans包含的類和接口數據庫

  二、  org.springframework.beans.annotation包含的類和接口express

  三、  org.springframework.beans.propertyeditors包含的類和接口編程

  四、  org.springframework.beans.support包含的類和接口設計模式

  五、  org.springframework.beans.factory包含的類和接口數組

  六、  org.springframework.beans.factory.annotation包含的類和接口

  七、  org.springframework.beans.factory.config包含的類和接口

  八、  org.springframework.beans.factory.parsing包含的類和接口

  九、  org.springframework.beans.factory.serviceloader包含的類和接口

  十、org.springframework.beans.factory.support包含的類和接口

  十一、org.springframework.beans.factory.wiring包含的類和接口

  十二、org.springframework.beans.factory.xml包含的類和接口

3、BeanDefinition解析

  (一)BeanDefinition是什麼

  (二)BeanDefinition屬性

  (三)BeanDefinition實現類

  (四)BeanDefinition的載入和解析

4、Bean默認標籤解析

  (一)默認標籤

  (二)bean標籤的解析及註冊

  (三)解析BeanDefinition

  (四)建立用於承載屬性的GenericBeanDefinition

  (五)解析各類屬性

5、Bean的加載

  (1)轉換對應的beanName

  (2)嘗試從緩存中加載單例

  (3)bean的實例化

  (4)原型模式(prototype)的依賴檢查

  (5)檢測parentBeanFactory

  (6)GenericBeanDefinition轉爲RootBeanDefinition

  (7)尋找依賴

  (8)依據scope建立bean

  (9)類型轉換

6、Bean的生命週期

  (1)ApplicationContext Bean生命週期

  (2)BeanFactory Bean生命週期

 

1、Spring框架簡介

  Spring框架是一個Java平臺,用來提供全面的基礎設施支持開發Java應用程序, Spring負責處理基礎設施部分,這樣你就能夠專一於應用程序部分。Spring框架內,把一級對象經過設計模式封裝起來,這樣你就能夠集成到本身的應用程序中而不用關注他們是如何在後臺工做的。

  目前,Spring框架按照功能組織成大約20個模塊。這些模塊分爲核心容器、數據訪問/集成、Web、AOP(面向切面的編程)、instrument(支持和類加載器的實現來在特定的應用服務器上使用)、消息和測試,以下圖所示。

從上面能夠看出Spring主要分紅六個模塊:

  1.Spring核心容器:核心容器是Spring框架的重要組成部分,也能夠說是Spring框架的基礎。他在整個框架中的做用是負責管理對象的建立,管理,配置等操做。其主要包含spring-core、spring-beans、spring-context、spring-expression組件。

  2.面向切面編程:Spring框架還提供了面向切面編程的能力,利用面向切面編程,能夠實現一些面向對象編程沒法很好實現的操做。例如,將日誌,事務與具體的業務邏輯解耦。其主要包含spring-aop、spring-aspects組件。

  3.Instrumentation:該模塊提供了爲JVM添加代理的功能,該模塊包含spring-instrument、spring-instrument-tomcat組件,使用較少,沒必要過度關注。

  4.數據訪問與集成:Spring框架爲了簡化數據訪問的操做,包裝了不少關於數據訪問的操做,提供了相應的模板。同時還提供了使用ORM框架的能力,能夠與不少流行的ORM框架進行整合,如hibernate,mybatis等等的著名框架。還實現了數據事務的能力,可以支持事務。包含spring-jdbc、spring-tx、spring-orm、spring-oxm、spring-jms、spring-messaging組件。

  5.Web和遠程調用:Spring框架支持Web開發,以及與其餘應用遠程交互調用的方案。包含spring-web、spring-webmvc、spring-websocket、spring-webmvc-portlet組件。

  6.Spring測試:Spring框架提供了測試的模塊,能夠實現單元測試,集成測試等等的測試流程,整合了JUnit或者TestNG測試框架。包含spring-test組件。

 

咱們爲何要使用Spring框架?簡單來講,使用Spring框架能夠帶來如下好處:

  一、輕量:非入侵性的、所依賴的東西少、資源佔用少、部署簡單,不一樣功能選擇不一樣的 jar 組合。

  二、容器:工廠模式實現對 JavaBean 進行管理,經過控制反轉(IOC)將應用程序的配置和依賴性與應用代碼分開。

  三、鬆耦合:經過 xml 配置或註解便可完成 bean 的依賴注入。

  四、AOP:經過 xml 配置 或註解便可加入面向切面編程的能力,完成切面功能,如日誌,事務等的統一處理。

  五、方便集成:經過配置和簡單的對象注入便可集成其餘框架,如 Mybatis、Hibernate。

  六、豐富的功能:JDBC層抽象、事務管理、MVC、Java Mail、任務調度、JMX、JMS、JNDI、EJB、動態語言、遠程訪問、Web Service等。

 

其中,最核心的就是上述的2和4:IOC(控制反轉)和AOP(面向切面編程)。

  IOC:在平時的java應用開發中,咱們要實現某一個功能或者說是完成某個業務邏輯時至少須要兩個或以上的對象來協做完成。在沒有使用Spring的時候,每一個對象在須要使用他的合做對象時,本身均要使用像new object() 這樣的語法來將合做對象建立出來,這個合做對象是由本身主動建立出來的,建立合做對象的主動權在本身手上,本身須要哪一個合做對象,就主動去建立,建立合做對象的主動權和建立時機是由本身把控的,而這樣就會使得對象間的耦合度高了。好比A對象須要使用合做對象B來共同完成一件事,A要使用B,那麼A就對B產生了依賴,也就是A和B之間存在一種耦合關係,而且是緊密耦合在一塊兒。而使用了Spring以後就不同了,建立合做對象B的工做是由Spring來作的,Spring建立好B對象,而後存儲到一個容器裏面,當A對象須要使用B對象時,Spring就從存放對象的那個容器裏面取出那個B對象,而後交給A對象使用,至於Spring是如何建立那個對象,以及何時建立好,A對象不須要關心這些細節問題,A獲得Spring給以後,兩個對象一塊兒協做完成要完成的工做便可。

  因此控制反轉是將建立對象的控制權進行轉移,之前建立對象的主動權和建立時機是由本身把控的,而如今這種權力轉移到第三方,好比轉移交給了IOC容器,它就是一個專門用來建立對象的工廠,你要什麼對象,它就給你什麼對象,有了 IOC容器,依賴關係就變了,原先的依賴關係就沒了,它們都依賴IOC容器了,經過IOC容器來創建它們之間的關係。

  AOP能夠說是OOP(Object Oriented Programming,面向對象編程)的補充和完善。OOP引入封裝、繼承、多態等概念來創建一種對象層次結構,用於模擬公共行爲的一個集合。不過OOP容許開發者定義縱向的關係,但並不適合定義橫向的關係,例如日誌功能。日誌代碼每每橫向地散佈在全部對象層次中,而與它對應的對象的核心功能毫無關係對於其餘類型的代碼,如安全性、異常處理和透明的持續性也都是如此,這種散佈在各處的無關的代碼被稱爲橫切,在OOP設計中,它致使了大量代碼的重複,而不利於各個模塊的重用。

  同OOP技術偏偏相反,AOP利用一種稱爲"橫切"的技術,剖解開封裝的對象內部,並將那些影響了多個類的公共行爲封裝到一個可重用模塊,並將其命名爲"Aspect",即切面。所謂"切面",簡單說就是那些與業務無關,卻爲業務模塊所共同調用的邏輯或責任封裝起來,便於減小系統的重複代碼,下降模塊之間的耦合度,並有利於將來的可操做性和可維護性。

 

2、Beans源碼文件清單

  spring項目源碼由多個子項目組成,如spring-beans,spring-context,spring-core,spring-aop,spring-web,spring-webmvc等,整個項目結構以下圖:

其中spring beans有以下的源文件包:

  一、org.springframework.beans:包含了操做java bean的接口和類。

  二、org.springframework.beans.annotation:支持包,提供對java 5註解處理bean樣式的支持。

  三、org.springframework.beans.propertyeditors:屬性編輯器,用來將string類型的值轉換爲object類型。

  四、org.springframework.beans.support:org.springframework.beans的支持包,好比一組bean的排序和保持工具類等。

  五、org.springframework.beans.factory:實現spring輕量級IOC容器的核心包。

  六、org.springframework.beans.factory.annotation:配置基於註解驅動的bean的支持包。

  七、org.springframework.beans.factory.config:bean工廠的SPI接口和配置相關的處理類。

  八、org.springframework.beans.factory.parsing:bean definition解析的支持基礎類。

  九、org.springframework.beans.factory.serviceloader:jdk1.6 ServiceLoader基礎類的支持包。

  十、org.springframework.beans.factory.support:org.springframework.beans.factory 包的支持類。

  十一、org.springframework.beans.factory.wiring:一種決定一個bean實例的元數據的機制。

  十二、org.springframework.beans.factory.xml:包含了一個基於xml的beanFactory實現,也包含一個標準的spring-beans的dtd。

 

  在介紹beans的類和接口以前,先理清下bean的概念,在 Spring 中,構成應用程序主幹並由Spring IOC容器管理的對象稱爲bean。bean是一個由Spring IOC容器實例化、組裝和管理的對象。簡而言之,bean是對象,並且由Spring中IOC容器進行管理,咱們的應用程序由一個個bean構成。

一、org.springframework.beans包含的類和接口

1.1  BeanInfoFactory:建立java.beans.BeanInfo實例的策略,定義了方法BeanInfo getBeanInfo()。

1.2 ExtendedBeanInfo:BeanInfo接口的實現類,BeanInfo接口是在java.beans包中的。

1.3 ExtendedBeanInfoFactory:BeanInfoFactory接口的實現,用來評估bean的class是否有不知足JavaBean規範的set方法,於是是否知足Spring ExtendedBeanInfo做爲內省的候選。

 

1.4 BeanWrapper:Spring底層JavaBean公共基礎的核心接口。一般不直接使用,而是經過BeanFactory間接使用。做用:提供對標準javabean的分析和操做方法:單個或者批量獲取和設置屬性值,獲取屬性描述符,查詢屬性的可讀性和可寫性等。支持屬性的嵌套設置,深度沒有限制。

1.5 CachedIntrospectionResults:內部類。在BeanWrapperImpl類中會用到,爲這個類的javabean緩存屬性描述信息,以提升效率,減少開銷。

1.6 BeanWrapperImpl:BeanWrapper的默認實現。能夠根據需求,將集合與數組的值轉換到對應目標對象的集合和數組。自定義的屬性編輯器經過屬性編輯器的setValue,setAsText方法實現上述的轉換功能。

 

1.7 Mergeable:表明一個對象的值能夠和父對象的值進行合併的接口。其主要的子類有:ManagedList、ManagedArray、ManagedMap、ManagedProperties、ManagedSet。這幾個類在org.springframework.beans.factory 包中。

1.8 BeanMetadataElement:傳送配置源對象的超級接口。定義了惟一的方法:Object getSource(),其子類和子接口以下圖:

 

1.9 BeanMetadataAttribute:bean definition定義中的屬性-鍵值對(key-value)容器。

1.10 BeanMetadataAttributeAccessor:AttributeAccessorSupport的拓展,爲了追蹤對象定義源。

 

1.11 GenericTypeAwarePropertyDescriptor:JavaBeans的PropertyDescriptor類的拓展,重載了getPropertyType函數。

1.12 PropertyDescriptorUtils:抽象類,PropertyDescriptor內部使用。PropertyDescriptor(屬性描述器)在軟件包 java.beans中,用來表示JavaBean 經過存儲器方法導出的一個屬性。

1.13 PropertyMatches:根據一個可配置的距離計算一個屬性的匹配度。可同時用於java bean的成員變量(fields)與屬性(properties)。其核心函數calculateStringDistance,利用Levenshtein算法計算兩個字符串的類似度。另解析下Java中成員變量(Fields)和屬性(Properties)的區別: 成員變量Fields就是定義的字段。根據SUN官方定義,屬性是指get或者set方法名去掉get或者set後,把剩餘的部分首字母改成小寫後,即爲這個類的屬性。

1.14 PropertyAccessor:獲取和設置屬性(例如對象bean的屬性,對象的Field)的通用接口,它用來做爲BeanWrapper的基礎接口。其繼承關係以下圖:

1.15  AbstractPropertyAccessor:PropertyAccessor接口的抽象實現。

1.16  AbstractNestablePropertyAccessor:繼承自AbstractPropertyAccessor,也是ConfigurablePropertyAccessor的一種,能夠爲典型的一些應用場景提供支持。

1.17 ConfigurablePropertyAccessor:PropertyAccessor配置方法的封裝接口。是BeanWrapper的父接口。

1.18 DirectFieldAccessor:ConfigurablePropertyAccessor接口的實現類,用來直接獲取實例的字段(f ield)。

1.19 PropertyAccessorFactory:獲取PropertyAccessor實例簡單工廠,特別是BeanWrapper實例(BeanWrapper繼承自PropertyAccessor)。

1.20 PropertyAccessorUtils:PropertyAccessor類獲取和設置屬性的一些工具方法。

 

1.21 PropertyEditorRegistrar:用一個屬性編輯器註冊器(PropertyEditorRegistry)註冊一個自定義的屬性編輯器(PropertyEditor)的策略接口。

1.22 PropertyEditorRegistry:屬性編輯器註冊器。封裝了JavaBean屬性編輯器的註冊方法。主要函數爲void registerCustomEditor()。

1.23 PropertyEditorRegistrySupport:PropertyEditorRegistry接口的基本實現類。主要做爲BeanWrapperImpl父類使用。

 

1.24 PropertyValue:一個對象,用來保存一個bean單獨屬性值信息。用對象來保存PropertyValue(name, value)信息,相對於map保存能夠提供更大的靈活性。

1.25 PropertyValues:包含了一個或者多個PropertyValue對象,一般用做特定的一個目的bean的屬性更新。

1.26 MutablePropertyValues:PropertyValues接口的默認實現,提供了對屬性的一些簡單操做,好比get、add、set、merge、remove方法等。

1.27 PropertyValuesEditor:PropertyValues 對象的編輯器。

 

1.28 TypeConverter:定義了類型轉換方法的接口。將值轉換成指定的類型。

1.29 TypeConverterDelegate:內部用的類,用來將屬性值轉換爲目標類型的值。

1.30 SimpleTypeConverter:TypeConverter接口的簡單實現,它不會針對一個特定的目標進行操做。

1.31 TypeConverterSupport:TypeConverter接口的基本實現類,使用了代理typeConverterDelegate。這個類主要用做BeanWrapperImpl的基類使用。

 

1.32 BeanUtils:JavaBeans的靜態工具方法,用來初始化bean,檢查bean屬性類型,複製bean屬性等。

 

1.33 BeansException:在beans包和子包中所拋出的全部異常的抽象超類。

1.34 BeanInstantiationException:bean初始化失敗時拋出的異常。

1.35 FatalBeanException:在bean包和子包中遇到的不可恢復問題拋出的異常,例如:當引用一個無效的bean屬性時拋出的InvalidPropertyException異常。

1.36 ConversionNotSupportedException:當一個bean的屬性沒有適合的編輯器或者轉換器時所拋出的異常。

1.37 MethodInvocationException:當一個bean屬性的get和set方法拋出異常時拋出該異常,相似於InvocationTargetException。

1.38 NullValueInNestedPathException:當獲取一個內嵌屬性路徑的屬性時遇到空指針異常時拋出的異常。

1.39 TypeMismatchException:當試圖設置bean屬性時拋出的類型不匹配異常。

1.40 InvalidPropertyException:遇到非法的bean property時異常類。

1.41 NotReadablePropertyException:當試圖獲取一個不可讀屬性的屬性值時拋出的異常,典型場景bean屬性沒有get方法。

1.42 NotWritablePropertyException:當試圖向一個不可寫屬性寫入屬性值時拋出的異常,典型場景bean屬性沒有set方法。.

1.43 PropertyAccessException:獲取屬性相關的異常超類,例如類型不匹配或者目標調用異常。

1.44 PropertyBatchUpdateException組合異常,由多個的單個PropertyAccessException實例組成。

 

二、org.springframework.beans.annotation包含的接口和類

2.1 AnnotationBeanUtils:JavaBean類型註解的通用工具方法。定義了一個靜態方法:public static void copyPropertiesToBean(),將指定Annotation的屬性複製到目標bean中。若是屬性在excludeProperties中定義了,那麼就不會被複制。

 

三、org.springframework.beans.propertyeditors包含的接口和類

  屬性編輯器,用來將string類型的值轉換成object類型的。他們都繼承自PropertyEditorSupport,這個類能夠用於自定義的類型轉換,繼承後重寫了public void setAsText(),public String getAsText() 兩個方法。注意PropertyEditor和PropertyEditorSupport都是java本身定義的,不是Spring的。包含的類有:

3.1  ByteArrayPropertyEditor

3.2  CharacterEditor

3.3  CharArrayPropertyEditor

3.4  CharArrayPropertyEditor

3.5  ClassArrayEditor

3.6  ClassEditor

3.7  CurrencyEditor

3.8  CustomBooleanEditor

3.9  CustomCollectionEditor

3.10  CustomDateEditor

3.11  CustomMapEditor

3.12  CustomNumberEditor

3.13  FileEditor

3.14  InputSourceEditor

3.15  InputStreamEditor

3.16  LocaleEditor

3.17  PathEditor

3.18  PatternEditor

3.19  PropertiesEditor

3.20  ReaderEditor

3.21  ResourceBundleEditor

3.22  StringArrayPropertyEditor

3.23 StringTrimmerEditor

3.24  StringTrimmerEditor

3.25  URIEditor

3.25  URLEditor

3.27  UUIDEditor

3.28  ZoneIdEditor

 

四、org.springframework.beans.support包含的接口和類

4.1  ArgumentConvertingMethodInvoker:MethodInvoker的子類,經過TypeConverter將真實目標方法的指定參數進行轉換。

4.2  MutableSortDefinition:SortDefinition接口的可變實現。支持在對同一個屬性值進行設置的時候能夠利用升序排列的值進行切換。

4.3  PagedListHolder:PagedListHolder是一個簡單的狀態保持,它處理一組對象,將它們分頁。分頁的起始頁從0開始。主要用在web網站的用戶界面上。

4.4  PropertyComparator:對兩個bean進行比較,經過BeanWrapper來比較指定bean的屬性。

4.5  ResourceEditorRegistrar:繼承了PropertyEditorRegistrar,使用資源編輯器來填充指定的PropertyEditorRegistry。

4.6  SortDefinition:根據一個指定的屬性對一組bean實例進行排序的定義類。isAscending爲True時進行升序排列,爲False進行降序排列。

 

五、org.springframework.beans.factory包含的接口和類

5.1  Aware:它是一個標籤,內部沒有任何屬性或者方法。它是一個超級接口,實現它的子接口的bean標誌着在spring容器中能夠被特定框架的對象通知到,經過回調方式的方法來完成這種通知。繼承關係以下圖:

5.2  BeanClassLoaderAware:容許一個獲取它的classLoader(即當前bean factory加載bean類使用的class loader)的回調類,實現了void setBeanClassLoader(ClassLoader classLoader)。

5.3  BeanFactoryAware:實現此接口的bean能夠獲取到它們本身的Beanfactory。好比,bean能夠經過factory尋找一些具備協做關係的beans。

5.4  BeanNameAware:實現此接口的bean能夠在一個bean factory中獲取到它們的bean名稱。可是須要注意的是,並不推薦一個經過一個bean name去定位bean,在外部配置中,這種對應關係並不嚴格對應。

5.5  NamedBean:對應BeanNameAware接口,返回bean的名稱。函數String getBeanName()。

 

5.6  BeanFactory:獲取spring bean容器的根接口。其主要函數有getBean()、getBeanProvider()、containsBean()、isSingleton()、isPrototype()、isTypeMatch()、getType()、getAliases()。其繼承關係以下圖:

5.7  BeanFactoryUtils:beanFactory上的操做方法工具類,特別是在ListableBeanFactory接口上。包括返回bean的個數,bean的名字,bean實例等,考慮到了一些具備嵌套關係的hierarchy factory,而若是這些方法在ListableBeanFactory中不須要考慮這些。

5.8  HierarchicalBeanFactory:子接口,實現此接口的bean factory具備層次結構便可以獲取父BeanFactory。方法 getParentBeanFactory()獲取父BeanFactory;方法containsLocalBean()判斷本地bean factory是否含有指定名字的bean,不考慮在父BeanFactory中的狀況。

5.9  ListableBeanFactory:beanFactory接口的實現,實現此接口的beanFactory能遍歷他們內部的全部bean實例,而不用根據客戶請求經過名字一個一個的去搜索bean。提供的函數以下:

  containsBeanDefinition();判斷factory是否包含指定命名的bean definition;

  getBeanDefinitionCount();返回在factory中定義的bean的個數;

  getBeanDefinitionNames();返回該factory中定義的全部bean的名字;

  getBeanNamesForType();返回指定類型的bean的名字;

  getBeansOfType();返回指定類型的bean實例;

  getBeanNamesForAnnotation(); 返回被指定的標籤標註的全部bean的名字;

  getBeansWithAnnotation();返回被指定標籤標註的全部bean實例。

 

5.10  FactoryBean:實現了此接口的bean不能看作一個一般意義上的bean,一個FactoryBean雖然以bean的形式來定義,但它暴露的對象(getObject())一般是它建立的對象,而不是做爲一個bean實例暴露本身。

5.11  SmartFactoryBean:FactoryBean接口的擴展實現。實現該接口能夠代表每次是否返回的都是獨立的實例,由於用isSingleton()函數判斷爲假,代表非單例模式,但這並不足以代表返回的都是獨立的實例。

 

5.12  ObjectFactory:一個對象工廠,當觸發時會返回全部對象的實例(能夠是共享的或者獨立的)。

5.13  ObjectProvider:繼承自ObjectFactory,ObjectFactory的一個變種,專門用來爲注入點服務。

5.14  InjectionPoint:注入點的簡單描述,指向一個方法或者構造函數的參數或者成員變量(field)。

5.15  InitializingBean:實現此接口的bean在BeanFactory設置爲它們的屬性時只須要執行一次,例如:初始化定製或者僅僅檢查必須存在的屬性是否已經設置完成等等。

5.16  SmartInitializingSingleton:回調接口,當一個bean工廠建立時,單例singleton實例化階段結束時被觸發。一些單例模式的bean能夠實現此接口,在單例實例作完一些規律性、常作的初始化能夠用來作一些初始化工做。以免突發的Early initialization產生的負面效果。好比ListableBeanFactory中的getBeansOfType函數調用。注:對於單件的初始化有(Lazy Initialization)和(Early initialization)兩種方法。

5.17  BeanCreationException:beanfactory在試圖經過bean definition建立一個bean時遇到錯誤而拋出的異常。

5.18  BeanCreationNotAllowedException:若當前不容許建立一個bean時(例如在beanFactory關閉過程當中)而試圖去獲取bean的請求時拋出的異常。

5.19  BeanCurrentlyInCreationException:一個bean的引用當前正在建立過程當中拋出的異常。

5.20  BeanDefinitionStoreException:beanFactory遇到一個無效的bean definition拋出的異常 。

5.21  BeanExpressionException:獲取一個表達式的值失敗時拋出的異常。

5.22  BeanInitializationException:bean初始化異常時拋出。

5.23  BeanIsAbstractException:當試圖獲取一個定義爲abstract的bean definition時拋出的異常。

5.24  BeanIsNotAFactoryException:當一個bean不是工廠,但用戶試圖經過給定bean名稱訪問工廠。

5.25  BeanNotOfRequiredTypeException:當一個bean的類型和指望類型不匹配時拋出的異常。

5.26  CannotLoadBeanClassException:BeanFactory不能加載指定bean的class類時拋出的異常。

5.27  FactoryBeanNotInitializedException:工廠bean沒有初始化異常。

5.28  NoSuchBeanDefinitionException:沒有該bean definition異常。

5.29 NoUniqueBeanDefinitionException:返回多個bean definition異常。

5.30  UnsatisfiedDependencyException:當有依賴檢查時,在bean factory定義中,bean的依賴或者屬性沒有指定時拋出的異常。

 

六、org.springframework.beans.factory.annotation包含的接口和類

6.1  AnnotatedBeanDefinition:BeanDefinition接口的擴展,BeanDefinition在org.springframework. beans.factory.config包中。

  它暴露了它的bean 類的AnnotationMetadata,不須要加載類。提供了一個getMetadata()方法來獲取該bean definition的註解元數據, ClassMetadata定義了一個特定類的抽象元數據,不須要加載此類便可訪問,主要方法有:

  1)String getClassName()返回該類的名稱。

  2)boolean isInterface()返回該類是不是接口。

  3)boolean isAbstract()返回該類是否爲抽象類。

  4)boolean isConcrete()返回該類是否爲具體類。

  5)boolean isFinal()返回該類是否爲final類。

  6)boolean hasSuperClass()返回該類是否有父類。

  7)String getSuperClassName()返回父類的名稱,沒有的話返回null。

  8)String[] getInterfaceNames()返回繼承的接口數組,若是沒有,返回空。

  9)String[] getMemberClassNames()返回引用的類的名稱。

6.2  AnnotatedGenericBeanDefinition:繼承自GernericBeanDefinition和AnnotatedBeanDefinition,經過暴露AnnotatedBeanDefinition接口來增長對註解元數據的支持。GernericBeanDefinition在org.springframework.beans.factory.support包中,是一站式的標準bean Definition。

 

Spring自帶依賴注入註解:

  1 @Required:依賴檢查;

  2 @Autowired:按類型自動裝配,用於替代基於XML配置的自動裝配。基於@Autowired的自動裝配,默認是根據類型注入,能夠用於構造器、字段、方法注入

  3 @Value:注入int、float、String等基本數據類型,只能標註在成員變量、setter方法上。

  4 @Qualifier:限定描述符,用於細粒度選擇候選者。@Qualifier限定描述符除了能根據名字進行注入,但能進行更細粒度的控制如何選擇候選者。@Qualifier(value = "限定標識符")

 

6.3  Required:public @interface Required 依賴檢查。

6.4  Autowired:public @interface Autowired:能夠對成員變量、方法和構造函數進行標註,來完成自動裝配的工做。

6.5  Value:public @interface Value:用於注入SpEL表達式,能夠放置在字段方法或參數上。

6.6  Qualifier:@Qualifier(value = "限定標識符") 。對應於基於XML配置中的標籤,@Qualifier限定描述符除了能根據名字進行注入,但能進行更細粒度的控制如何選擇候選者@Qualifier(value = "限定標識符") 。

6.7  Configurable:@Configurable 註解中的autowire屬性就可讓Spring來自動裝配。

 

6.8  RequiredAnnotationBeanPostProcessor(@required註解實現類):實現了BeanPostProcessor,對配置了Required註解的javaBean屬性進行強制檢查。

6.9  AutowiredAnnotationBeanPostProcessor (Autowired註解實現類):實現了BeanPostProcessor接口,它自動綁定註解的field,setter方法和任意配置方法。AutowiredAnnotationBeanPostProcessor 間接繼承了BeanPostProcessor,它自動綁定註解的field,setter方法和任意的配置方法。當檢測到5個java註解時這些成員被注入其中。spring默認的註解爲@Autowired和@Value。另外:也支持JSR-330的@inject註解,做爲@Autowired的替代方案。

6.10  AnnotationBeanWiringInfoResolver(@configurable註解實現):繼承自BeanWiringInfoResolver,使用configurable的註解來查找哪些類須要自動綁定。設置 @Configurable 註解中的autowire屬性就可讓Spring來自動裝配:@Configurable(autowire= Autowire.BY_TYPE) 或者 @Configurable(autowire=Autowire.BY_NAME,這樣就能夠按類型或者按名字自動裝配了。

6.11  QualifierAnnotationAutowireCandidateResolver(@qualifier的註解實現類):間接實現了AutowireCandidateResolver,對要自動綁定的field或者參數和bean definition根據@qualifier註解進行匹配。同時也支持經過@value註解來綁定表達式的值。AutowireCandidateResolver是一個策略接口,由它來決定特定的bean definition對特定的依賴是否能夠做爲一個自動綁定的候選項。

6.12  InitDestroyAnnotationBeanPostProcessor(初始化和銷燬方法的註解實現類):間接繼承了BeanPostProcessor,實現了經過註解來初始化init和銷燬destroy方法。是spring的InitializingBean和DisposableBean回調接口的註解實現。

 

6.13  BeanFactoryAnnotationUtils:關聯註解的bean的查詢的工具方法,例如spring的@Qualifier註解。

6.14  CustomAutowireConfigurer:繼承了BeanFactoryPostProcessor,它使自定義的自動綁定qualifier類型的註冊更便利。.

6.15  InjectionMetadata:管理注入元數據的內部類。

6.16  Lookup:@Lookup的註解,這是一個做用在方法上的註解,被其標註的方法會被重寫,而後根據其返回值的類型,容器調用BeanFactory的getBean()方法來返回一個bean。

好比:若是有一個類C,須要用到類B,若是使用@Autowired註解注入B,那麼B每次調用都是同一個對象,即便B不是單例的,如今我但願每次調用B都是不同的,那麼實現方案有2個:方案A : 每次從容器中獲取B;方案B: 使用@lookup註解。

6.17  ParameterResolutionDelegate:代理類,用來解析外部構造函數或方法上的自動裝配的參數。

6.18 Autowire:決定自動綁定狀態的枚舉,即一個bean的依賴是否由spring容器使用setter方式自動注入。這個是spring DI的核心概念。

 

七、org.springframework.beans.factory.config包含的接口和類

FactoryBean和BeanFactory區別:

  FactoryBean:Spring 中有兩種類型的Bean,一種是普通Bean,另外一種是工廠Bean 即 FactoryBean。FactoryBean跟普通Bean不一樣,其返回的對象不是指定類的一個實例,而是該FactoryBean的getObject方法所返回的對象。建立出來的對象是否屬於單例由isSingleton中的返回決定。Spring自身就提供了70多個FactoryBean的實現。它們隱藏了實例化一些複雜Bean的細節,給上層應用帶來了便利。FactoryBean 一般是用來建立比較複雜的bean,通常的bean 直接用xml配置便可,但若是一個bean的建立過程當中涉及到不少其餘的bean 和複雜的邏輯,用xml配置比較困難,這時能夠考慮用FactoryBean。

  BeanFactory:以Factory結尾,表示它是一個工廠類(接口), 是負責生產和管理bean的一個工廠。在Spring中,BeanFactory是IOC容器的核心接口,它的職責包括:實例化、定位、配置應用程序中的對象及創建這些對象間的依賴。BeanFactory只是個接口,並非IOC容器的具體實現,可是Spring容器給出了不少種實現,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等。

 

7.1  AbstractFactoryBean:實現了FactoryBean的簡單模板超類,它根據singleton標誌來決定是建立一個單例仍是一個prototype對象。

7.2  ListFactoryBean:共享一組(list)實例的簡單工廠bean。

7.3  MapFactoryBean:共享一組(map)實例的簡單工廠bean。

7.4  SetFactoryBean:共享set實例的簡單工廠bean。

7.5  MethodInvokingFactoryBean:一個有返回值的工廠bean,它返回觸發一個靜態或者實例的方法的結果。

7.6  MethodInvokingBean:一個簡單的method invoker bean,和MethodInvokingFactoryBean不一樣,它並不返回觸發一個方法的結果,而是僅僅返回觸發一個目標方法。

7.7  FieldRetrievingFactoryBean:檢索靜態或者非靜態Field的值的工廠bean。

7.8  PropertyPathFactoryBean:經過給定目標對象計算屬性路徑的工廠bean。

7.9  ObjectFactoryCreatingFactoryBean:一個有返回值的工廠bean,它返回ObjectFactory。

7.10  ProviderCreatingFactoryBean:返回一個JSR-330 Provider的工廠bean,JSR-330 Provider反過來從beanFactory返回一個bean資源。JSR-330 是 Java 的依賴注入標準。

7.11  ServiceLocatorFactoryBean:繼承自FactoryBean,在beanFactory中建立一個動態代理,來代理一個具備一個或者多個服務或者類型的接口。

7.12  PropertiesFactoryBean:它支持從classpath位置的文件中讀取屬性實例的工廠bean。

7.13  YamlMapFactoryBean:爲讀取YAML源文件的Map的工廠,保持YAML聲明的值類型和結構的原樣。

7.14  YamlProcessor:YAML 是專門用來寫配置文件的語言,很是簡潔和強大,遠比 JSON 格式方便。它實質上是一種通用的數據串行化格式。該類做爲YAML factories基類。

7.15  YamlPropertiesFactoryBean:從YAML源文件中讀取屬性的工廠,用來暴露字符串屬性值扁平型組織結構。

 

7.16  AutowireCapableBeanFactory:beanFactory的擴展接口,實現了自動綁定功能。這個接口的兩個主要方法是:autowire:使用給定的自動綁定策略,來給一個類的新實例進行初始化。autowireBeanProperties使用名稱或者類型來自動綁定給定bean實例的屬性。

7.17  ConfigurableBeanFactory:將會被大部分beanFactory實現的配置接口。爲對bean factory進行配置提供一些功能服務,包括BeanFactory接口中的一些函數。這個接口並不用於普通的應用代碼,而是用於同BeanFactory或 ListableBeanFactory一塊兒出現使用。

7.18  ConfigurableListableBeanFactory:將會被大部分ListablebeanFactory實現的配置接口。除了ConfigurableBeanFactory,該接口也提供分析和修改bean definitions的功能函數,也能預實例化單例對象。

       

7.19  BeanDefinition:一個bean實例的描述,它含有屬性值、構造參數值。它的實現子類還提供更多的信息。bean的定義BeanDefinition,包裝BeanWrapper是java bean的基礎。能夠這麼說,是spring的基石,再怎麼強調它的重要性都不爲過。

  BeanDefinition 做用:一個BeanDefinition描述了一個bean的實例,包括屬性值,構造方法參數值和繼承自它的類的更多信息。BeanDefinition僅僅是一個最簡單的接口,主要功能是容許BeanFactoryPostProcessor,例如PropertyPlaceHolderConfigure(PropertyPlaceholderConfigurer是BeanFactoryPostProcessor的一個重要實現)可以檢索並修改屬性值和別的bean的元數據。

  BeanDefinition的繼承關係:(1)父接口:AttributeAccessor、BeanMetadataElement。其中,AttributeAccessor接口定義了最基本的對任意對象的元數據的修改或者獲取,BeanMetadataElement接口提供了一個getResource()方法,用來傳輸一個可配置的源對象。(2)子接口:AnnotatedBeanDefinition。(3)子類: AbstractBeanDefinition、AnnotatedGenericBeanDefinition、ChildBeanDefinition、GenericBeanDefinition、RootBeanDefinition、ScannedGenericBeanDefinition。

7.20  BeanDefinitionCustomizer:定製一個給定的bean definition的回調函數,用在Lambda 表達式或者方法引用中。

7.21  BeanDefinitionHolder:使用名稱或者別名來保存BeanDefinition。能夠爲內部bean做爲佔位符註冊。

7.22  BeanDefinitionVisitor:遍歷BeanDefinition對象的參觀者類,特別是也遍歷bean中的屬性值和構造參數值,解析bean的元數據值。在PlaceholderConfigurerSupport中被使用,用來解析包含在BeanDefinition中全部的字符串值,解析發現的全部佔位符。

 

7.23  BeanPostProcessor:容許對一個新的bean實例進行定製修改的工廠鉤子。

7.24  BeanFactoryPostProcessor:容許對一個applicationContext中的bean definition進行定製修改的工廠鉤子,修改context內含的bean factory中bean的屬性值。

7.25  DestructionAwareBeanPostProcessor:BeanPostProcessor的子接口,它增長了一個銷燬前回調方法。

7.26  InstantiationAwareBeanPostProcessor:BeanPostProcessor的子接口,它增長了一個初始化前回調方法,還有一個在初始化後但顯式設置屬性或者自動綁定發生前的回調方法。

7.27  InstantiationAwareBeanPostProcessorAdapter:實現了SmartInstantiationAwareBeanPostProcessor全部方法的適配器,它沒有任何操做,不會改變容器對bean進行初始化的處理過程。

7.28  SmartInstantiationAwareBeanPostProcessor:InstantiationAwareBeanPostProcessor的擴展接口,它增長了對一個處理過bean的最終類型進行預測的回調方法。

 

7.29  CustomEditorConfigurer:繼承自BeanFactoryPostProcessor,給自定義屬性編輯器的註冊提供了便利的方法。

7.30  CustomScopeConfigurer:BeanFactoryPostProcessor的簡單實現,給自定義Scope的註冊提供了便利的方法,上面提到ConfigurableBeanFactory提供了Scope的註冊。

7.31  PreferencesPlaceholderConfigurer:PropertyPlaceholderConfigurer的子類,支持JDK1.4中的Preferences API (java.util.prefs)

7.32  PropertyOverrideConfigurer:屬性資源配置器,它支持在applicationContext中重寫一個bean的屬性值。

7.33  PropertyPlaceholderConfigurer:PlaceholderConfigurerSupport的子類,它解析本地屬性或者系統屬性或者環境變量定義的佔位符(以${}描述)。

7.34  PropertyResourceConfigurer:支持從一個屬性資源中對單個bean的屬性值進行配置。

 

7.35  BeanExpressionContext:計算一個BeanDefinition內部的表達式的容器對象。

7.36  BeanExpressionResolver:經過計算一個表達式來解析爲值的策略接口。

7.37  EmbeddedValueResolver:StringValueResolver適配器,用於解析ConfigurableBeanFactory佔位符和表達式。

7.38  BeanReference:暴露bean名稱的引用接口。這個接口並不須要實際指向一個bean實例,只須要邏輯指向bean的名字。

7.39  RuntimeBeanNameReference:固定佔位符類,當在beanfactory中做爲另一個bean名稱的引用時,做爲屬性值對象,將在運行時進行解析。

7.40  RuntimeBeanReference:固定佔位符類,當在beanfactory中做爲另一個bean的引用時,做爲屬性值對象,將在運行時進行解析。

7.41  TypedStringValue:保存一個類型的屬性值。

7.42  ConstructorArgumentValues:保存構造方法的參數值,特別是做爲Beandefinition的一部分。

7.43  DependencyDescriptor:將要注入的特定依賴的描述。

7.44  DeprecatedBeanWarner:繼承自BeanFactoryPostProcessor,記錄@Deprecated bean的報警信息。

7.45  PlaceholderConfigurerSupport:屬性資源配置器的抽象基類,它解析BeanDefinition中屬性值的佔位符。

7.46  AutowiredPropertyMarker:簡單的標記類,用於自動裝載屬性值,增長到BeanDefinition的getPropertyValues()函數爲一個指定的bean 屬性。

 

7.47  NamedBeanHolder:給定名字的bean實例的簡單佔位符。

7.48  SingletonBeanRegistry:定義了共享bean實例的註冊接口。

7.49  Scope:ConfigurableBeanFactory使用的策略接口,表明了bean實例所在的做用域。Bean的做用域就是指Bean實例的生存空間或者有效範圍。scope=[singleton, prototype, request, session, global session]

  一、singleton(單實例):在每一個Spring IOC容器中,一個Bean定義對應一個對象實例。這是Spring容器默認的做用域。當一個Bean的做用域爲Singleton時,Spring IOC容器中只會存在一個共享的Bean實例,而且全部對Bean的請求,只要id與該Bean定義相匹配,就只會返回Bean的同一個實例。這個單一實例會被存儲到單例緩存(Singleton Cache)中,而且全部針對該Bean的後續請求和引用都將返回被緩存的對象實例。單實例模式對於無會話狀態的Bean(DAO組件、業務邏輯組件)來講是理想的選擇。

  二、prototype(原型模式):一個bean定義對應多個對象實例。prototype做用域的Bean在每次對該Bean請求時都會建立一個新的Bean實例,對須要保持會話狀態的Bean(Struts2中充當控制器的Action類)應該使用prototype做用域。spring不能對一個原型模式Bean的整個生命週期負責,容器在初始化、裝配好一個原型模式實例後,將它交給客戶端,就再也不過問了。所以,客戶端要負責原型模式實例的生命週期管理。

  三、request:在一次Http請求中,容器會返回該Bean的同一個實例,而對於不一樣的用戶請求,會返回不一樣的實例。該做用域僅在基於Web的Spring ApplicationContext情形下有效。

  四、session:在一次HttpSession中,容器會返回該Bean的同一個實例。而對於不一樣的HttpSession請求,會返回不一樣的實例。該做用域僅在基於Web的Spring ApplicationContext情形下有效。

  五、global session:在全局的HTTPSession中,容器會返回該Bean的同一個實例。僅在使用portlet context時有效。

 

八、org.springframework.beans.factory.parsing包含的接口和類

8.1  AbstractComponentDefinition:ComponentDefinition接口的基本實現,提供了getDescription()來代理ComponentDefinition.getName()方法。

8.2  BeanComponentDefinition:基於一個標準BeanDefinition的ComponentDefinition,暴露指定bean的指定beanDefinition,內部BeanDefinition和BeanReference。

8.3  ComponentDefinition:描述在同一配置的Context中一組BeanDefinition和BeanReference的邏輯視圖的接口。

8.4  CompositeComponentDefinition:保存了一個或者多個內嵌ComponentDefinition實例的ComponentDefinition實現,它把這些ComponentDefinition實例聚合成具備命名的組。

8.5  AliasDefinition:表明在解析進程中一個別名已經被註冊。

8.6  ImportDefinition:在解析進程中,表明一個import已經被處理。

8.7  DefaultsDefinition:一個默認definition標識接口,繼承了BeanMetadataElement,沒有實現任何方法。

 

8.8  ConstructorArgumentEntry:表明了構造參數。

8.9  BeanEntry:表明了一個BeanDefinition。

8.10  PropertyEntry:表明了一個javaBean的屬性。

8.11  QualifierEntry:表明了一個自動綁定的備選qualifier。

 

8.12  EmptyReaderEventListener:ReaderEventListener接口的空實現,全部回調方法都沒有提供可執行操做。

8.13  ReaderEventListener:接受在讀取BeanDefinition進程中註冊組件、別名、import時的回調接口。

 

8.14  FailFastProblemReporter:ProblemReporter接口的簡單實現,當遇到錯誤發生時展現fail-fast行爲。

8.15  ProblemReporter:SPI接口,支持tool或者外部進程處理在beanDefinition解析期間報出的錯誤或者異常。

 

8.16  PassThroughSourceExtractor:SourceExtractor的簡單實現,它經過一個attachment來傳遞備選的源數據類型對象。

8.17  NullSourceExtractor:SourceExtractor接口的簡單實現,返回null做爲source元數據。

8.18  SourceExtractor:簡單策略接口,容許工具控制source元數據關聯到bean definition元數據。

 

8.19  Location:模型接口,一個資源位置的模型。

8.20  ParseState:在解析進程中做爲一個簡單的基於棧結構的追蹤邏輯位置類。

8.21  Problem:表明了一個beanDefinition配置問題。

8.22  ReaderContext:bean definition讀取進程中傳遞的一個Context,封裝了全部相關的配置,包括狀態。

8.23  BeanDefinitionParsingException:一個bean definition驗證失敗時拋出異常的異常類。

 

九、org.springframework.beans.factory.serviceloader包含的接口和類

9.1  AbstractServiceLoaderBasedFactoryBean:FactoryBean的抽象基類,它是操做JDK1.6 ServiceLoader的基礎工具。

9.2  ServiceFactoryBean:暴露指定配置的服務類的基礎服務的FactoryBean,經過JDK1.6 serviceLoader基礎類來獲取這些服務。

9.3  ServiceListFactoryBean:暴露配置的服務類的全部基礎服務的FactoryBea,表現爲一組服務對象,能夠經過JDK1.6 serviceLoader基礎類來獲取這些服務。

9.4  ServiceLoaderFactoryBean:暴露指定配置服務類的JDK1.6 serviceLoader的FactoryBean。

十、org.springframework.beans.factory.support包含的接口和類

10.1  DefaultListableBeanFactory:是beans包中最核心的一個類,ListableBeanFactory接口和BeanDefinitionRegistry接口的默認實現:基於beanDefinition對象的一個成熟的beanFactory。BeanDefinitionRegistry(在此包中)提供了beanDefinition的管理。AbstractAutowireCapableBeanFactory(在此包中)實現屬性的自動綁定功能。ConfigurableListableBeanFactory(在org.springframework.beans.factory.config包中)提供了對bean定義的分析和修改的便利方法,同時也提供了對單例的預實例化。

  Serializable接口是Java提供的序列化接口,是一個空接口,爲對象提供標準的序列化和反序列化操做。它的源代碼是public interface Serializable{},即什麼都沒有,是一個標識接口。在Java中的這個Serializable接口是給JVM看的,告訴JVM,我不作這個類的序列化了,你(JVM)給我序列化。當咱們讓實體類實現此接口,實際上是告訴JVM此類能夠被序列化,可被默認的序列化機制序列化。那什麼是序列化,做用是什麼?序列化就是將一個對象及其狀態轉換成字節碼,保存起來(能夠保存在數據庫、內存、文件等),而後能夠在適當的時候再將其狀態恢復(也就是反序列化)。有兩個應用場景:一是想把內存中的對象狀態保存到一個文件或者數據庫中,二是想將對象經過網絡進行傳輸的時候。

  DefaultListableBeanFactory是經過實現上述4個特定的功能的接口、抽象類來完成的,是一個成熟的bean factory。spring IOC容器的實現,從根源上是beanfactory,但真正能夠做爲一個獨立使用的IOC容器仍是DefaultListableBeanFactory,所以能夠說DefaultListableBeanFactory是整個spring IOC的始祖。它能夠做爲一個單獨的BeanFactory,也可做爲自定義BeanFactory的父類。其繼承關係以下圖:

  (1)類入口處提供了一個靜態方法:

javaxInjectProviderClass=ClassUtils.forName("javax.inject.Provider",DefaultListableBeanFactory.class.getClassLoader());

  ClassUtils(在包org.springframework.util裏)提供了對類的實用方法,主要用在框架內部。這個靜態方法返回了javax.inject.Provider的一個實例。  包 javax.inject 指定了獲取對象的一種方法,該方法與構造器、工廠這些傳統方法相比能夠得到更好的可重用性、可測試性以及可維護性。此方法的處理過程就是你們熟知的依賴注入。javax.inject.Provider其語法:public interface Provider,提供了一個T的實例,一般做爲一個依賴注入容器的父接口,能夠注入任何類型的T,固然也能夠注入Provider,相對於直接注入,有幾個好處:檢索多個實例,延遲或者選擇性的檢索一個實例,打破循環依賴,抽象的scope,能夠從一個包含scope的更小的scope中檢索一個實例。

  (2)繼承自AbstractAutowireCapableBeanFactory的方法

  提供bean的建立(有construct方法),屬性注值,綁定(包括自動綁定)和初始化。處理運行時bean引用,解析管理的集合,調用初始化方法。

  最主要的實現的模板方法是:AutowireCapleBeanFactory類(在包org.springframework.beans. factory.config中,AbstractAutowireCapableBeanFactory實現此接口)中的方法resolveDependency(DependencyDescriptor, String, Set, TypeConverter)。這個方法用來實現類型的自動綁定AbstractAutowireCapableBeanFactory.copyConfigurationFrom(ConfigurableBeanFactory otherFactory)

  (3)繼承自ListableBeanFactory接口的方法

  ListableBeanFactory(在包org.springframework.beans.factory中)是beanFactory接口的擴展接口,它能夠枚舉全部的bean實例,而不是客戶端經過名稱一個一個的查詢得出全部的實例。要預加載全部的bean定義的beanfactory能夠實現這個接口來。該接口定義了訪問容器中Bean基本信息的若干方法,如查看Bean的個數、獲取某一類型Bean的配置名、查看容器中是否包括某一Bean等方法;

繼承自該接口的方法有:containsBeanDefinition()、findAnnotationOnBean() 、getBeanDefinitionCount() 、getBeanDefinitionNames()、getBeanNamesForType() 、getBeansOfType() 、getBeansWithAnnotation() 。

  (4)繼承自ConfigurableListableBeanFactory接口的方法

  ConfigurableListableBeanFactory(在包org.springframework.beans.factory.config中)同時繼承了ListableBeanFactory,AutowireCapableBeanFactory和ConfigurableBeanFactory,提供了對bean定義的分析和修改的便利方法,同時也提供了對單例的預實例化。

  繼承該接口的方法有:freezeConfiguration() 、getBeanDefinition()、ignoreDependencyInterface() 、ignoreDependencyType() 、isAutowireCandidate() 、isConfigurationFrozen() 、preInstantiateSingletons()、registerResolvableDependency() 。

  (5)繼承自BeanDefinitionRegistry接口的方法

  BeanDefinitionRegistry:Spring配置文件中每個節點元素在Spring容器裏都經過一個BeanDefinition對象表示,它描述了Bean的配置信息。而BeanDefinition Registry接口提供了向容器手工註冊BeanDefinition對象的方法。

  繼承該接口的方法有:containsBeanDefinition() 、getBeanDefinition()、getBeanDefinitionCount()、getBeanDefinitionNames() 、isBeanNameInUse() 、registerBeanDefinition() 、removeBeanDefinition() 。

  (6)序列化支持

  private void writeObject(java.io.ObjectOutputStream out);

  private void readObject(java.io.ObjectInputStream in);

  private void readObjectNoData()。

10.2  StaticListableBeanFactory:靜態BeanFactory的實現,用來編程實現註冊已經存在的單例實例。

10.3  AbstractBeanFactory:BeanFactory的抽象基類實現,提供ConfigurableBeanFactory SPI的所有功能。

  在此簡單介紹下SPI機制。SPI全稱Service Provider Interface,一種服務發現機制。是Java提供的一套用來被第三方實現或者擴展的接口,它能夠用來啓用框架擴展和替換組件。SPI的做用就是爲這些被擴展的API尋找服務實現。SPI 的本質是將接口實現類的全限定名配置在文件中,並由服務加載器讀取配置文件,加載實現類。能夠在運行時,動態爲接口替換實現類。能夠很容易的經過 SPI 機制爲程序提供拓展功能。

10.4  AbstractAutowireCapableBeanFactory:抽象beanFactory的超類,它使用指定的RootBeanDefinition類的全部方法實現建立默認bean。

 

10.5  AbstractBeanDefinition:具體、成熟BeanDefinition類的基類,構造出RootBeanDefinition和ChildBeanDefinition的通用屬性。

10.6  RootBeanDefinition:根BeanDefinition,表示在運行時期的spring BeanFactory中一個合併的BeanDefinition。

10.7  ChildBeanDefinition:從父類繼承各類設置的bean的beanDefinition。

10.8  GenericBeanDefinition:通用BeanDefinition是一站式的標準bean Definition。

10.9  BeanDefinitionReader:bean definition解析器的簡單接口。

10.10  BeanDefinitionReaderUtils:BeanDefinitionReader實現使用的工具方法類。

10.11  AbstractBeanDefinitionReader:實現了BeanDefinitionReader接口,是beanDefinitionReader的抽象基類。

10.12  PropertiesBeanDefinitionReader:簡單屬性格式的BeanDefinitionReader。

10.13  BeanDefinitionDefaults:簡單保持BeanDefinition的默認屬性類。

10.14  BeanDefinitionBuilder:使用建造者模式構建BeanDefinition的編程方法。

10.15  BeanDefinitionRegistry:持有beanDefinition的註冊接口,例如RootBeanDefinition和ChildBeanDefinition實例。

10.16  SimpleBeanDefinitionRegistry:BeanDefinitionRegistry接口的簡單實現。

10.17  BeanDefinitionRegistryPostProcessor:標準BeanFactoryPostProcessor SPI的擴展接口,容許在常規BeanFactoryPostProcessor檢查以前註冊更多bean definition。

10.18  BeanDefinitionResource:繼承自AbstractResource,描述BeanDefinition的資源。在此介紹一下Spring使用的一種設計模式:裝飾器模式。裝飾器模式容許向一個現有的對象添加新的功能,同時又不改變其結構。裝飾者能夠在所委託被裝飾者的行爲以前或以後加上本身的行爲,以達到特定的目的(如:功能的加強)。

10.19  BeanDefinitionValueResolver:主要用在bean工廠實施中,解析bean definition對象中的value,根據目標bean實例轉換成真正的值。

10.20  BeanDefinitionValidationException:驗證一個bean definition時出錯拋出的異常。

10.21  BeanDefinitionOverrideException:BeanDefinitionStoreException一個子類,顯示一個在嘗試一個非法的重載。好比爲同一個bean name註冊一個新的definition,可是DefaultListableBeanFactory的isAllowBeanDefinitionOverriding卻爲false的時候。

                 

10.22  ManagedArray:集合類,用來保存它所管理的array元素,它能夠包含運行時期的bean引用(將被解析爲bean對象)。

10.23  ManagedList:集合類,用來保存它所管理的List元素,它能夠包含運行時期的bean引用(將被解析爲bean對象)。

10.24  ManagedMap:集合類,用來保存它所管理的array值,它能夠包含運行時期的bean引用(將被解析爲bean對象) 。

10.25  ManagedSet:集合類,用來保存它所管理的set值,它能夠包含運行時期的bean引用(將被解析爲bean對象) 。

10.26  ManagedProperties:表示一個spring管理的屬性實例,它支持父/子 definition的合併。

       

10.27  AutowireCandidateQualifier:解析自動綁定備選項Qualifier。

10.28  AutowireCandidateResolver:策略接口,對特定的依賴,這個接口決定一個特定的bean definition是否知足做爲自動綁定的備選項。

10.29  SimpleAutowireCandidateResolver:繼承自AutowireCandidateResolver,當出現不支持的註解時使用。

10.30  GenericTypeAwareAutowireCandidateResolver:繼承自SimpleAutowireCandidateResolver,一個通用的AutowireCandidateResolver。

10.31  AutowireUtils:工具類,爲具備自動裝載能力的bean工廠提供一些有用的方法。

 

10.32  LookupOverride:表示能夠重寫一個在同一個IOC上下文中查找對象的方法。

10.33  MethodOverride:表示重寫對象,它針對IOC容器所管理對象的方法的重寫。

10.34  MethodOverrides:一組方法重寫,決定了在運行時期對spring IOC容器管理對象的重寫方法(若是存在的話)。

10.35  ReplaceOverride:MethodOverride的擴展,表示一個IOC容器方法的任意重寫。

 

10.36  InstantiationStrategy:負責根據相應的根bean definition建立實例的接口。

10.37  SimpleInstantiationStrategy:BeanFactory中簡單對象的初始化策略。

10.38  CglibSubclassingInstantiationStrategy:BeanFactory默認對象初始化策略。

 

10.39  BeanNameGenerator:對beanDefinition產生bean名稱的策略接口。

10.40  DefaultBeanNameGenerator:BeanNameGenerator接口的默認實現,代理BeanDefinitionReaderUtils.generateBeanName(BeanDefinition, BeanDefinitionRegistry)方法。

10.41  SecurityContextProvider:運行在beanFactory中的安全Context的提供者。

10.42  SimpleSecurityContextProvider:SecurityContextProvider的簡單擴展。

10.43  DefaultSingletonBeanRegistry:共享bean實例的通用註冊,實現了SingletonBeanRegistry。

10.44  FactoryBeanRegistrySupport:一個支持單例註冊(須要處理FactoryBean實例)的基類,集合了DefaultSingletonBeanRegistry對單例的管理功能。

10.45  ConstructorResolver:解析構造函數和工程方法的代理。對構造函數的解析主要經過參數匹配來實現。

10.46  DisposableBeanAdapter:對一個給定的bean實例進行銷燬bean及進行銷燬的相關工做的適配器。

  這裏簡單介紹適配器模式:適配器就是爲了實現接口而作的,若是不用適配器,你去實現接口的話,須要實現接口中的全部方法,這要那個就會帶來一些麻煩,可是若是你使用了適配器,就能夠定義一個類去實現接口,而後當你用哪一個方法的時候直接繼承該類就好了,這個類就是適配器了。適配器模式的意義是要將一個接口轉變成另外一個接口,它的目的是經過改變接口來達到重複使用的目的。而裝飾器模式不是要改變被裝飾對象的接口,而是偏偏要保持原有的接口,可是加強原有對象的功能,或者改變原有對象的處理方式而提高性能。

10.47  MethodReplacer:一個能夠從新定義IOC容器對象的全部方法的接口:方法注入是依賴注入的一種形式。

10.48  MergedBeanDefinitionPostProcessor:後處理回調接口,在運行時合併bean definition。

10.49  NullBean:一個空bean的內部表示,好比調用FactoryBean的getObect()或者其餘的工廠方法返回的是null值。

10.50  ImplicitlyAppearedSingletonException:繼承自IllegalStateException,一個內部使用的異常類,在ConstructorResolver引起,傳遞給初始化DefaultSingletonBeanRegistry。

十一、org.springframework.beans.factory.wiring包含的接口和類

11.1  BeanConfigurerSupport:配置bean的便利基類,它能夠對對象進行依賴注入。典型應用就是做爲切面的子類使用。

11.2  BeanWiringInfo:保存特定類的bean的綁定元數據信息。在對註解和切面進行鏈接時使用。

11.3  BeanWiringInfoResolver:策略接口,可以根據給定的一個新初始化的bean對象解析bean的名稱信息。在此簡單介紹下策略模式:用意是針對一組算法,將每個算法封裝到具備共同接口的獨立類中,從而使得它們能夠相互替換。策略模式使得算法能夠在不影響到客戶端的狀況下發生變化。通俗的講就是遇到一種問題有多種解法的時候,咱們能夠根據環境或者條件的不一樣選擇不一樣的算法或者策略來完成該功能。

11.4  ClassNameBeanWiringInfoResolver:BeanWiringInfoResolver的簡單默認實現,查找一個和全限定名同名的bean的名稱。

十二、org.springframework.beans.factory.xml包含的接口和類

12.1  AbstractBeanDefinitionParser:BeanDefinitionParser的抽象實現,提供了許多便利方法和模板方法,模板方法須要在子類進行重寫來提供具體的邏輯實現。

12.2  AbstractSimpleBeanDefinitionParser:AbstractBeanDefinitionParser的簡單實現,當將要解析元素的屬性名和配置類的屬性名一一對應的時候,能夠用到該類。

12.3  AbstractSingleBeanDefinitionParser:BeanDefinitionParser的基類,須要解析和定義單獨的BeanDefinition。

12.4  BeanDefinitionDecorator:DefaultBeanDefinitionDocumentReader用來處理自定義的,內嵌的標籤的接口 。

12.5  BeanDefinitionDocumentReader:解析包含spring BeanDefinition的xml文件的SPI。

12.6  DefaultBeanDefinitionDocumentReader:BeanDefinitionDocumentReader接口的默認實現。

12.7  BeanDefinitionParser:DefaultBeanDefinitionDocumentReader用來處理自定義的,高層的標籤的接口 。

12.8  BeanDefinitionParserDelegate:狀態代理類,用來解析xml BeanDefinition。

       

12.9  BeansDtdResolver:spring bean dtd解析器EntityResolver的實現,用來從classpath或者jar文件加載dtd。

  DTD(Documnet Type Definition)即文檔類型定義,是一種XML約束模式語言,是XML文件的驗證機制,屬於XML文件組成的一部分。DTD 是一種保證XML文檔格式正確的有效方法,能夠經過比較XML文檔和DTD文件來看文檔是否符合規範,元素和標籤使用是否正確。

  XSD(XML Schemas Definition)XML Schema語言也就是XSD。XML Schema描述了XML文檔的結構。能夠用一個指定的XML Schema來驗證某個XML文檔,以檢查該XML文檔是否符合其要求。文檔設計者能夠經過XML Schema指定一個XML文檔所容許的結構和內容,並可據此檢查一個XML文檔是不是有效的。XML Schema自己是一個XML文檔,它符合XML語法結構。能夠用通用的XML解析器解析它。

  XSD和DTD相比:DTD是使用非XML語法編寫的,不可擴展,不支持命名空間,只提供很是有限的數據類型。XSD可跟據未來的條件可擴展,比DTD豐富和有用,用XML書寫,支持數據類型,支持命名空間。

12.10  DefaultNamespaceHandlerResolver:NamespaceHandlerResolver接口的默認實現。

12.11  DelegatingEntityResolver:EntityResolver的實現,分別代理了dtd的BeansDtdResolver和xml schemas的 PluggableSchemaResolver。

12.12  NamespaceHandlerResolver:DefaultBeanDefinitionDocumentReader用來定位NamespaceHandler的接口。

12.13  PluggableSchemaResolver:繼承自EntityResolver,使用一系列map文件將schema url解析到本地classpath資源。

12.14  ResourceEntityResolver:繼承自EntityResolver,經過ResourceLoader來解析實體的引用。

 

12.15  XmlBeanDefinitionReader:Bean definition reader for XML bean definitions。

12.16  XmlBeanDefinitionStoreException:繼承自BeanDefinitionStoreException。

12.17  XmlBeanFactory:過時,從spring 3.2 後推薦使用DefaultListableBeanFactory和XmlBeanDefinitionReader來代替它。

12.18  XmlReaderContext:ReaderContext的擴展,通常和XmlBeanDefinitionReader一塊兒使用。

 

12.19  NamespaceHandler:實現了特定的URI命名空間。

12.20  NamespaceHandlerSupport:支持實現自定義的NamespaceHandler。

12.21  SimpleConstructorNamespaceHandler:單NamespaceHandler實現,它將自定義屬性直接映射到bean屬性。

12.22  SimplePropertyNamespaceHandler:簡單NamespaceHandler實現,它將自定義屬性直接映射到bean屬性。

12.23  UtilNamespaceHandler:工具命名空間的NamespaceHandler。

 

12.24  DocumentDefaultsDefinition:簡單的javaBean,它保存標準的spring xml文件中級別的屬性,如:default-lazy-init,default-autowire等等。

12.25  DocumentLoader:加載xml文件的策略接口。

12.26  DefaultDocumentLoader:spring 的DocumentLoader默認實現。

12.27  ParserContext:傳遞一個beanDefinition 解析進程到此上下文,封裝了全部的相關配置也包括狀態。

 

3、BeanDefinition解析

  其實Spring的org.springframework.beans包下面全部的類主要解決了三件事情:Bean的定義,Bean的建立,Bean的解析。對於使用者來講,惟一須要關心的就是Bean的建立,其餘兩個由Spring在內部幫你完成,對用戶來講是透明的。

  Bean的定義就是完整的描述了在Spring的配置文件中你定義節點中全部的信息,包括各類子節點。Bean的定義主要由BeanDefinition描述。當Spring成功解析你定義的節點後,在Spring的內部就被轉換成BeanDefinition對象,之後全部的操做都是對這個對象完成的。

(一)BeanDefinition是什麼?

  BeanDefinition 描述了一個Bean實例,它包含了Bean 的屬性值,構造器參數,同時包含有更多其餘的建立這個Bean的信息。更通俗點來說:BeanDefinition包含了創造一個Bean所須要的全部信息,屬性,構造函數參數以及訪問它們的方法,是一個Bean的元數據。

BeanDefinition在Spring中是用來描述Bean對象的,其自己不是一個bean實例,僅僅是包含bean實例的全部信息,好比屬性值、構造器參數以及其餘信息。Bean對象建立是根據BeanDefinition中描述的信息來建立的,BeanDefinition存在的做用是爲了能夠方便的進行修改屬性值和其餘元信息,好比經過BeanFactoryPostProcessor進行修改一些信息,而後在建立Bean對象的時候就能夠結合原始信息和修改後的信息建立對象了。

(二)BeanDefinition屬性

  在講BeanDefinition的屬性以前,咱們先一塊兒看看BeanDefinition的繼承體系。以下圖,BeanDefinition繼承圖:

 

下面咱們看看BeanDefinition的屬性:

  (1)id:Bean 的惟一標識名。它必須是合法的 XMLID,在整個 XML 文檔中惟一。

  (2)name:用來爲 id 建立一個或多個別名。它能夠是任意的字母符合。多個別名之間用逗號或空格分開。

  (3)class:用來定義類的全限定名(包名+類名)。只有子類 Bean 不用定義該屬性。

  (4)parent:子類 Bean 定義它所引用它的父類 Bean。這時前面的 class 屬性失效。子類 Bean 會繼承父類 Bean 的全部屬性,子類 Bean 也能夠覆蓋父類 Bean 的屬性。注意:子類 Bean 和父類 Bean 是同一個 Java 類。

  (5)abstract(默認爲」false」):用來定義 Bean 是否爲抽象 Bean。它表示這個 Bean 將不會被實例化,通常用於父類 Bean,由於父類 Bean 主要是供子類 Bean 繼承使用。

  (6)lazy-init(默認爲「default」):用來定義這個 Bean 是否實現懶初始化。若是爲「true」,它將在 BeanFactory 啓動時初始化全部的 SingletonBean。反之,若是爲「false」,它只在 Bean 請求時纔開始建立 SingletonBean。

  (7)autowire(自動裝配,默認爲「default」):它定義了 Bean 的自動裝載方式。「no」:不使用自動裝配功能。」byName」:經過 Bean 的屬性名實現自動裝配。」byType」:經過 Bean 的類型實現自動裝配。「constructor」:相似於 byType,但它是用於構造函數的參數的自動組裝。「autodetect」:經過 Bean 類的檢討機制(introspection)決定是使用「constructor」仍是使用「byType」。

  (8)depends-on(依賴對象):這個 Bean 在初始化時依賴的對象,這個對象會在這個 Bean 初始化以前建立。

  (9)init-method:用來定義 Bean 的初始化方法,它會在 Bean 組裝以後調用。它必須是一個無參數的方法。

  (10)destroy-method:用來定義 Bean 的銷燬方法,它在 BeanFactory 關閉時調用。一樣,它也必須是一個無參數的方法。它只能應用於 singletonBean。

  (11)factory-method:定義建立該 Bean 對象的工廠方法。它用於下面的「factory-bean」,表示這個 Bean 是經過工廠方法建立。此時,「class」屬性失效。

  (12)factory-bean:定義建立該 Bean 對象的工廠類。若是使用了「factory-bean」則「class」屬性失效。

  (13)autowire-candidate:採用 xml 格式配置 bean 時,將元素的 autowire-candidate屬性設置爲 false,這樣容器在查找自動裝配對象時,將不考慮該 bean,即它不會被考慮做爲其它 bean自動裝配的候選者,可是該 bean 自己仍是能夠使用自動裝配來注入其它 bean 的。

  (14)MutablePropertyValues:用於封裝標籤的信息,其實類裏面就是有一個 list,list裏面是 PropertyValue 對象,PropertyValue 就是一個 name 和 value 屬性,用於封裝標籤的名稱和值信息。

  (15)ConstructorArgumentValues:用於封裝標籤的信息,其實類裏面就是有一個 map,map 中用構造函數的參數順序做爲 key,值做爲 value 存儲到 map 中。

  (16)MethodOverrides:用於封裝 lookup-method 和 replaced-method 標籤的信息,一樣的類裏面有一個 Set 對象添加 LookupOverride 對象和 ReplaceOverride 對象。

(三)BeanDefinition實現類

  bean definition的實現類共有三個,分別爲ChildBeanDefinition,RootBeanDefinition,GenericBeanDefinition。

  一、ChildBeanDefinition:是一種bean definition,它能夠繼承它父類的設置,即ChildBeanDefinition對RootBeanDefinition有必定的依賴關係。ChildBeanDefinition從父類繼承構造函數參數值、屬性值,並能夠重寫父類的方法,同時也能夠增長新的屬性或者方法。若指定初始化方法、銷燬方法或者靜態工廠方法,ChildBeanDefinition將重寫相應父類的設置。depends on、 autowire mode、dependency check、singleton、lazy int通常由子類自行設定。

  二、RootBeanDefinition:一個RootBeanDefinition定義代表它是一個可合併的bean definition:即在spring beanFactory運行期間,能夠返回一個特定的bean。RootBeanDefinition能夠做爲一個重要的通用的bean definition 視圖。

  三、GenericBeanDefinition:能夠有效替代ChildBeanDefinition的絕大部分使用場合。是一站式標準的bean definition,除了具備指定類、可選的構造參數值和屬性參數這些其餘bean definition同樣的特性外,它還具備經過parenetName屬性來靈活設置parent bean definition。一般,GenericBeanDefinition用來註冊用戶可見的bean definition(可見的bean definition意味着能夠在該類 bean definition上定義post-processor來對bean進行操做,甚至爲配置parent name作拓展準備)。RootBeanDefinition和ChildBeanDefinition用來預約義具備parent child關係的bean definition。

(四)BeanDefinition的載入和解析

  對於IOC容器來講,這個載入過程,至關於把定義的BeanDefinition在IOC容器中轉換成一個Spring內部表示的數據結構的過程。IOC容器對Bean的管理和依賴注入功能的實現,是經過對其持有的BeanDefinition進行各類操做來完成的。這些BeanDefinition數據在IOC容器中經過一個HashMap來保持和維護。

  一、下面從DefaultListableBeanFactory入手,看下IOC容器是怎樣完成BeanDefinition載入的。在開始分析以前,先回到IOC容器初始化入口,也就是看一下refresh方法。這個方法的最初是在FileSystemXmlApplicationContext的構造函數中被調用的,它的調用標誌着容器初始化的開始,這些初始化化對象就是BeanDefinition數據。對於容器啓動來講,refresh是一個很重要的方法。該方法在AbstractApplicationContext類(是FileSystemXMLApplicationContext的基類)中,它詳細描述了整個ApplicationContext的初始化過程,好比BeanFactory的更新,MessageSource和PostProcessor的註冊等等。這個執行過程爲Bean的生命週期管理提供了條件。下面代碼顯示了對IOC容器執行refresh過程:

 1     public void refresh() throws BeansException, IllegalStateException {
 2         synchronized (this.startupShutdownMonitor) {
 3             // Prepare this context for refreshing.
 4             prepareRefresh();
 5             // 這裏是在子類中啓動refreshBeanFactory()的地方
 6             ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
 7             // Prepare the bean factory for use in this context.
 8             prepareBeanFactory(beanFactory);
 9 
10             try {
11                 // 設置BeanFactory的後置處理
12                 postProcessBeanFactory(beanFactory);.
13                 // 調用BeanFactory的後處理器,這些後處理器是在Bean定義中向容器註冊的
14                 invokeBeanFactoryPostProcessors(beanFactory);
15                 // 註冊Bean的後處理器,在Bean建立過程當中調用
16                 registerBeanPostProcessors(beanFactory);
17                 // 對上下文中的消息源進行初始化
18                 initMessageSource();
19                 // 初始化上下文中的事件機制
20                 initApplicationEventMulticaster();
21                 // 初始化其餘的特殊Bean
22                 onRefresh();
23                 // 檢查監聽Bean而且將這些Bean向容器註冊
24                 registerListeners();
25                 // 實例化全部的(non-lazy-init)單件
26                 finishBeanFactoryInitialization(beanFactory);
27                 // 發佈容器事件,結束Refresh過程
28                 finishRefresh();
29             }
30 
31             catch (BeansException ex) {
32                 if (logger.isWarnEnabled()) {
33                     logger.warn("Exception encountered during context initialization - " +
34                             "cancelling refresh attempt: " + ex);
35                 }
36                 // 爲防止Bean資源佔用,在異常處理中,銷燬已經在前面過程當中生成的單件Bean
37                 destroyBeans();
38                 // 重置 'active'標誌
39                 cancelRefresh(ex);
40                 // Propagate exception to caller.
41                 throw ex;
42             }
43 
44             finally {
45                 // Reset common introspection caches in Spring's core, since we
46                 // might not ever need metadata for singleton beans anymore...
47                 resetCommonCaches();
48             }
49         }
50     }

  二、進入到AbstractRefreshableAppliccationContext的refreshBeanFactroy()方法中,在這個方法中建立了BeanFactory。在建立IOC容器前,若是已經有容器存在,那麼須要把已有的容器銷燬和關係,保證refresh之後使用的都是新創建起來的IOC容器。

  三、當創建好了當前的IOC容器之後,開始了對容器的初始化,好比BeanDefinition的載入。以下圖所示:

 

  這裏調用的loadBeanDefinitions其實是一個抽象方法,loadBeanDefinitions在AbstractRefreshableApplicationContext的子類AbstractXmlApplicationContext中的實現,在這個loadBeanDefinitions中,初始化了讀取器XMLBeanDefinitionReader,而後把這個讀取器在IOC容器中設置好。最後是啓動讀取器來完成BeanDefinition在IOC容器中的載入。接着就是loadBeanDefinitions調用的地方,首先獲得BeanDefinition信息的Resource定位,而後直接調用XMLBeanDefinitionReader來讀取,具體的載入過程是委託給BeanDefinitionReader來完成的。由於這裏的BeanDefinition是經過XML文件來定義的,因此這裏使用XMLBeanDefinitionReader來載入BeanDefinition到容器中。

  四、經過以上對實現原理分析,在初始化FileSystemXmlApplicationContext的過程當中是經過調用IOC容器的refresh來啓動整個BeanDefinition的載入過程的,這個初始化是經過定義的XmlBeanDefinitionReader來完成的。同時咱們知道實際使用IOC容器是DefaultListableBeanFactory,具體的Resource載入在XmlBeanDefinitionReader讀入BeanDefinition時實現。由於Spring能夠對應不一樣形式的BeanDefinition。因爲這裏使用的是Xml方式的定義,全部須要使用XMLBeanDefinitionReader。若是使用了其餘的BeanDefinition方式,就須要使用其餘的BeanDefinitionReader來完成數據的載入工做。

 

4、Bean默認標籤解析

  Spring的標籤分爲默認標籤和自定義標籤,Spring用節點的命名空間來判斷是默認仍是自定義標籤。若是節點的命名空間爲http://www.Springframework.org/schema/beans就認爲是默認標籤,不然就認爲是自定義標籤。

(一)默認標籤

  默認標籤的解析在DefaultBeanDefinitionDocumentReader(在org.springframework.beans.factory.xml包中)類的parseDefaultElement方法中:

 1     private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
 2         if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
 3             importBeanDefinitionResource(ele);
 4         }
 5         else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
 6             processAliasRegistration(ele);
 7         }
 8         else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
 9             processBeanDefinition(ele, delegate);
10         }
11         else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
12             // recurse
13             doRegisterBeanDefinitions(ele);
14         }
15     }

  方法的邏輯很清晰,按默認標籤是import、alias、bean、beans四類狀況分別處理。其中,bean標籤的解析最爲複雜。

 

(二)bean標籤的解析及註冊(對應上述代碼中processBeanDefinition(ele, delegate))

  在此先簡單介紹下bean標籤,該標籤用於聲明一個類,在啓動 Spring 框架的時候根據該配置的類建立對象到容器裏面。屬性以下所示:

<bean>標籤:用於聲明一個類,在啓動Spring框架的時候根據該配置的類建立對象到容器裏面

        name:設置對象名(惟一標識符)

        id:設置對象名(惟一標識符,功能和name同樣)

        class:用於指定對象對應的類名,若是不是實現類必需要將bean聲明爲抽象的!

        scope:用於設置的對象的做用範圍,可選參數以下:

           *singleton:單例(默認)

               對象出生:當程序加載配置文件建立容器時,建立

               對象活着:只要容器還在,一直活着

               對象死亡:應用中止,容器銷燬,對象死亡

           *prototype:多例(原型對象)

               對象出生:當程序加載配置文件建立容器時建立(每次調用會建立一個新對象)

               對象活着:只要對象被使用,一直活着

               對象死亡:對象長時間不用,會被Java垃圾回收機制回收 (該對象不被容器管理)

           *reqeust:web項目中,Spring將建立的對象放在request做用域中

           *session:web項目中,Spring將建立的對象放在session做用域中

       init-method:設置建立對象的時候,調用初始化方法

       destroy-method:設置對象被回收時,調用註銷的方法

<bean name="customerServiceImpl" class="cn.mgy.service.impl.CustomerServiceImpl"></bean>

  首先咱們來看看processBeanDefinition(ele,delegate)方法,對bean標籤的解析進行一個大體上的流程瞭解:

 1     /**
 2      * Process the given bean element, parsing the bean definition
 3      * and registering it with the registry.
 4      */
 5     protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
 6         BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
 7         if (bdHolder != null) {
 8             bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
 9             try {
10                 // Register the final decorated instance.
11                 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
12             }
13             catch (BeanDefinitionStoreException ex) {
14                 getReaderContext().error("Failed to register bean definition with name '" +
15                         bdHolder.getBeanName() + "'", ele, ex);
16             }
17             // Send registration event.
18             getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
19         }
20     }

對上述代碼進行分析:

  一、BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement (ele);首先委託BeanDefinitionParserDelegate類(在org.springframework.beans. factory.xml包中)的parseBeanDefinitionElement()方法進行元素的解析,返回BeanDefinitionHolder類的實例bdHolder(return new BeanDefinitionHolder( beanDefinition, beanName, aliasesArray);)。方法調用完成後,bdHolder實例就包含咱們配置的各類屬性了,例如:class、name、id、alias之類的屬性。

  二、if (bdHolder != null)當返回的bdHolder不爲空的狀況下,若存在默認標籤的子節點下面還有自定義的屬性,還須要再次對自定義的標籤進行解析。

  三、BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());解析完成後,須要對解析後的bdHolder進行註冊,註冊委託給了BeanDefinitionReaderUtils(在包org.springframework.beans.factory.support中)的registerBeanDefinition方法。

  四、getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));發出響應事件,通知相關的監聽器,該bean加載完成。

 

(三)解析BeanDefinition(對應上述代碼的BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele))

  下面詳細分析下BeanDefinitionHolder bdHolder = delegate. parseBeanDefinitionElement(ele);,進入BeanDefinitionParserDelegate的parseBeanDefinitionElement()方法:

 1     /**
 2      * Parses the supplied {@code <bean>} element. May return {@code null}
 3      * if there were errors during parse. Errors are reported to the
 4      * {@link org.springframework.beans.factory.parsing.ProblemReporter}.
 5      */
 6     @Nullable
 7     public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
 8     /*********提取元素中的id以及name屬性*********/
 9         //解析id屬性
10         String id = ele.getAttribute(ID_ATTRIBUTE);
11         //解析name屬性
12         String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
13         //分割name屬性
14         List<String> aliases = new ArrayList<>();
15         if (StringUtils.hasLength(nameAttr)) {
16             //將name屬性的值經過,; 進行分割 轉爲字符串數字(即在配置文件中如配置多個name在此作處理)
17             String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
18             aliases.addAll(Arrays.asList(nameArr));
19         }
20 
21         String beanName = id;
22         // 若是ID爲空 使用配置的第一個name屬性做爲ID
23         if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
24             beanName = aliases.remove(0);
25             if (logger.isTraceEnabled()) {
26                 logger.trace("No XML 'id' specified - using '" + beanName +
27                         "' as bean name and " + aliases + " as aliases");
28             }
29         }
30 
31         if (containingBean == null) {
32             // 校驗beanName和aliases的惟一性
33             // 內部核心爲使用usedNames集合保存全部已經使用了的beanName和alisa
34             checkNameUniqueness(beanName, aliases, ele);
35         }
36     /*********進一步解析其餘全部屬性到GenericBeanDefinition對象中*********/
37         AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
38     /*********若是檢測到Bean沒有指定beanName,那麼使用默認規則爲此Bean生成對應的beanName*********/
39         if (beanDefinition != null) {
40             if (!StringUtils.hasText(beanName)) {
41                 try {
42                     if (containingBean != null) {
43                         beanName = BeanDefinitionReaderUtils.generateBeanName(
44                                 beanDefinition, this.readerContext.getRegistry(), true);
45                     }
46                     else {
47                         beanName = this.readerContext.generateBeanName(beanDefinition);
48                         // Register an alias for the plain bean class name, if still possible,
49                         // if the generator returned the class name plus a suffix.
50                         // This is expected for Spring 1.2/2.0 backwards compatibility.
51                         String beanClassName = beanDefinition.getBeanClassName();
52                         if (beanClassName != null &&
53                                 beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
54                                 !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
55                             aliases.add(beanClassName);
56                         }
57                     }
58                     if (logger.isTraceEnabled()) {
59                         logger.trace("Neither XML 'id' nor 'name' specified - " +
60                                 "using generated bean name [" + beanName + "]");
61                     }
62                 }
63                 catch (Exception ex) {
64                     error(ex.getMessage(), ele);
65                     return null;
66                 }
67             }
68             String[] aliasesArray = StringUtils.toStringArray(aliases);
69     /*********將獲取到的信息封裝到BeanDefinitionHolder的實例中*********/
70             return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
71         }
72 
73         return null;
74     }

  上述代碼即是對默認標籤解析的全過程。在對屬性展開解析以前,Spring在外層又作了一個當前層的功能架構。重點看「進一步解析其餘全部屬性到GenericBeanDefinition對象中」,對應的代碼爲AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);,是一個重載函數,進入其代碼:

 1     /**
 2      * Parse the bean definition itself, without regard to name or aliases. May return
 3      * {@code null} if problems occurred during the parsing of the bean definition.
 4      */
 5     @Nullable
 6     public AbstractBeanDefinition parseBeanDefinitionElement(
 7             Element ele, String beanName, @Nullable BeanDefinition containingBean) {
 8 
 9         this.parseState.push(new BeanEntry(beanName));
10         //解析class屬性
11         String className = null;
12         if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
13             className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
14         }
15         //解析parent屬性
16         String parent = null;
17         if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
18             parent = ele.getAttribute(PARENT_ATTRIBUTE);
19         }
20 
21         try {
22             //建立用於承載屬性的AbstractBeanDefinition類型的GenericBeanDefinition
23             AbstractBeanDefinition bd = createBeanDefinition(className, parent);
24             //硬編碼解析默認bean的各類屬性
25             parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
26             //提取description
27             bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
28             //解析元數據
29             parseMetaElements(ele, bd);
30             //解析lookup-Method屬性
31             parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
32             //解析replaced-method屬性
33             parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
34             //解析構造函數參數
35             parseConstructorArgElements(ele, bd);
36             //解析property子元素
37             parsePropertyElements(ele, bd);
38             //解析qualifier子元素
39             parseQualifierElements(ele, bd);
40 
41             bd.setResource(this.readerContext.getResource());
42             bd.setSource(extractSource(ele));
43 
44             return bd;
45         }
46         catch (ClassNotFoundException ex) {
47             error("Bean class [" + className + "] not found", ele, ex);
48         }
49         catch (NoClassDefFoundError err) {
50             error("Class that bean class [" + className + "] depends on not found", ele, err);
51         }
52         catch (Throwable ex) {
53             error("Unexpected failure during bean definition parsing", ele, ex);
54         }
55         finally {
56             this.parseState.pop();
57         }
58 
59         return null;
60     }

 

(四)建立用於承載屬性的GenericBeanDefinition(對應上述代碼的AbstractBeanDefinition bd = createBeanDefinition(className, parent))

  BeanDefinition是一個接口,詳見(3、BeanDefinition解析)。有三個對應它的實現:RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition。這三種實現均繼承了AbstractBeanDefinition,其中BeanDefinition是配置文件元素標籤在容器中的內部表示形式。元素有class、scope、lazy-init等配置屬性。BeanDefinition則提供了相應的beanClass、scope、lazyInit屬性,二者的屬性是一一對應的。在配置文件中能夠定義父和子,父用RootBeanDefinition表示,而子用ChildBeanDefinition表示,而沒有父的就使用RootBeanDefinition表示。AbstractBeanDefinition對二者共同的類信息進行抽象。Spring經過BeanDefinition將配置文件中的配置信息轉換爲容器的內部表示,並將這些BeanDefinition註冊到BeanDefinitionRegistry中。Spring容器的BeanDefinitionRegistry就像是Spring配置信息的內存數據庫,主要以map形式進行保存,後續操做直接從BeanDefinitionRegistry中讀取配置信息。要解析屬性首先要建立用於承載屬性的實例,也就是建立GenericBeanDefinition類型的實例。對應的代碼爲AbstractBeanDefinition bd = createBeanDefinition(className, parent),進入該函數:

 1     /**
 2      * Create a bean definition for the given class name and parent name.
 3      * @param className the name of the bean class
 4      * @param parentName the name of the bean's parent bean
 5      * @return the newly created bean definition
 6      * @throws ClassNotFoundException if bean class resolution was attempted but failed
 7      */
 8     protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)
 9             throws ClassNotFoundException {
10 
11         return BeanDefinitionReaderUtils.createBeanDefinition(
12                 parentName, className, this.readerContext.getBeanClassLoader());
13     }

  繼續跟蹤下去:進入BeanDefinitionReaderUtils類(在包org.springframework.beans.factory.support中)中的函數:

 1     /**
 2      * Create a new GenericBeanDefinition for the given parent name and class name,
 3      * eagerly loading the bean class if a ClassLoader has been specified.
 4      * @param parentName the name of the parent bean, if any
 5      * @param className the name of the bean class, if any
 6      * @param classLoader the ClassLoader to use for loading bean classes
 7      * (can be {@code null} to just register bean classes by name)
 8      * @return the bean definition
 9      * @throws ClassNotFoundException if the bean class could not be loaded
10      */
11     public static AbstractBeanDefinition createBeanDefinition(
12             @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {
13 
14         GenericBeanDefinition bd = new GenericBeanDefinition();
15         bd.setParentName(parentName);
16         // parentName可能爲空
17         if (className != null) {
18             //若是classLoader不爲空,則使用傳入的classLoader同一虛擬機加載類對象
19             if (classLoader != null) {
20                 bd.setBeanClass(ClassUtils.forName(className, classLoader));
21             }
22             //不然只記錄classLoader
23             else {
24                 bd.setBeanClassName(className);
25             }
26         }
27         return bd;
28     }

  至此createBeanDefinition() 已經解析完,並且咱們也得到了用於承載屬性的AbstractBeanDefinition了。


(五)解析各類屬性(對應(三)解析BeanDefinition中的代碼 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);)

  上述已經建立了bean信息的承載實例,接下來就能夠進行bean信息的各類屬性分析了。進入parseBeanDefinitionAttributes方法,此方法是對Element全部的元素屬性進行分析。該方法也在類BeanDefinitionParserDelegate中。

 1     /**
 2      * Apply the attributes of the given bean element to the given bean * definition.
 3      * @param ele bean declaration element
 4      * @param beanName bean name
 5      * @param containingBean containing bean definition
 6      * @return a bean definition initialized according to the bean element attributes
 7      */
 8     public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
 9             @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
10         //scope和singleton兩種屬性只能指定其中之一,不能夠同時出現,不然Spring會拋出異常
11         if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
12             error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
13         }
14         //解析scope屬性
15         else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
16             bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
17         }
18         else if (containingBean != null) {
19             //在嵌入BeanDefinition狀況下且沒有單獨指定scope屬性則使用父類默認的屬性
20             bd.setScope(containingBean.getScope());
21         }
22         //解析abstract屬性
23         if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
24             bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
25         }
26         //解析lazy-init屬性
27         String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
28         if (isDefaultValue(lazyInit)) {
29             lazyInit = this.defaults.getLazyInit();
30         }
31         //若沒有設置或者設置成其餘字符都會被設置爲false
32         bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
33         //解析autowire屬性
34         String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
35         bd.setAutowireMode(getAutowireMode(autowire));
36         //解析depends-on屬性
37         if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
38             String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
39             bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
40         }
41         //解析autowire-candidate屬性
42         String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
43         if (isDefaultValue(autowireCandidate)) {
44             String candidatePattern = this.defaults.getAutowireCandidates();
45             if (candidatePattern != null) {
46                 String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
47                 bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
48             }
49         }
50         else {
51             bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
52         }
53         //解析primary屬性
54         if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
55             bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
56         }
57         //解析init-method屬性
58         if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
59             String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
60             bd.setInitMethodName(initMethodName);
61         }
62         else if (this.defaults.getInitMethod() != null) {
63             bd.setInitMethodName(this.defaults.getInitMethod());
64             bd.setEnforceInitMethod(false);
65         }
66         //解析destroy-method屬性
67         if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
68             String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
69             bd.setDestroyMethodName(destroyMethodName);
70         }
71         else if (this.defaults.getDestroyMethod() != null) {
72             bd.setDestroyMethodName(this.defaults.getDestroyMethod());
73             bd.setEnforceDestroyMethod(false);
74         }
75         //解析factory-method屬性
76         if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
77             bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
78         }
79         //解析factory-bean屬性
80         if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
81             bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
82         }
83 
84         return bd;
85     }

  在完成上面步驟後,也就是對bean全部的屬性的解析後,將會把獲取到的信息都封裝到BeanDefinitionHolder中(在包org.springframework.beans.factory.config中)。查看其構造函數:

1 public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName, @Nullable String[] aliases) {
2     Assert.notNull(beanDefinition, "BeanDefinition must not be null");
3     Assert.notNull(beanName, "Bean name must not be null");
4     this.beanDefinition = beanDefinition;
5     this.beanName = beanName;
6     this.aliases = aliases;
7 }
  以上就是對bean標籤的解析。

5、Bean的加載

  下面一段簡單的代碼能夠做爲Spring代碼加載的入口:MyTestBean myTestBean = (MyTestBean) beanFactory.getBean("myTestBean");。Spring經過調用BeanFactory的getBean()方法來加載bean。getBean()方法的真正實如今類AbstractBeanFactory中(在org.springframework.beans.factory.support包中),看下該方法的源碼:

  1     /**
  2      * Return an instance, which may be shared or independent, of the specified bean.
  3      * @param name the name of the bean to retrieve
  4      * @param requiredType the required type of the bean to retrieve
  5      * @param args arguments to use when creating a bean instance using explicit arguments
  6      * (only applied when creating a new instance as opposed to retrieving an existing one)
  7      * @param typeCheckOnly whether the instance is obtained for a type check,
  8      * not for actual use
  9      * @return an instance of the bean
 10      * @throws BeansException if the bean could not be created
 11      */
 12     @SuppressWarnings("unchecked")
 13     protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
 14             @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
 15     /***************************(1)轉換對應的beanName ***************************/
 16         // 提取對應的bean名稱
 17         final String beanName = transformedBeanName(name);
 18         Object bean;
 19     /***************************(2)嘗試從緩存中加載單例 **************************/
 20         // 檢查緩存中或者實例工廠中是否有對應的實例,直接嘗試從緩存中獲取或者singletonFactories中的ObjectFactory中獲取
 21         // 爲何會首先使用這段代碼?
 22         // 由於在建立單例bean的時候會存在依賴注入的狀況,而在建立依賴的時候爲了不循環依賴
 23         // Spring建立bean的原則是不等bean建立完成就會將建立bean的ObjectFactory提前曝光
 24         // 也就是將ObjectFactory加入到緩存中,一旦下個bean建立的時候須要依賴上個bean則直接使用ObjectFactory
 25         Object sharedInstance = getSingleton(beanName);
 26         if (sharedInstance != null && args == null) {
 27             if (logger.isTraceEnabled()) {
 28                 if (isSingletonCurrentlyInCreation(beanName)) {
 29                     logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
 30                             "' that is not fully initialized yet - a consequence of a circular reference");
 31                 }
 32                 else {
 33                     logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
 34                 }
 35             }
 36     /******************************(3)bean的實例化 ******************************/
 37             // 若是從緩存中獲得了bean的原始狀態,則須要對bean進行實例化。
 38             // 有時候存在諸如BeanFactory的狀況並非直接返回實例自己而是返回指定方法返回的實例
 39             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 40         }
 41         // 緩存中取不到
 42         else {
 43             // 只有在單例狀況下才會嘗試解決循環依賴;
 44             // 原型模式狀況下,若是存在A中有B的屬性,B中有A的屬性,那麼當依賴注入的時候,就會產生當A還未建立完的時候由於
 45             // 對於B的建立再次返回到建立A,形成循環依賴,也就是下面的狀況。對於「prototype」做用域Bean,Spring容器沒法完成依賴注入,
 46             // 由於「prototype」做用域的Bean,Spring容器不進行緩存,所以沒法提早暴露一個建立中的Bean。
 47     /**********************(4)原型模式(prototype)的依賴檢查 **********************/
 48             if (isPrototypeCurrentlyInCreation(beanName)) {
 49                 throw new BeanCurrentlyInCreationException(beanName);
 50             }
 51     /*************************(5)檢測parentBeanFactory **************************/
 52             //確認是否存在父類工廠
 53             BeanFactory parentBeanFactory = getParentBeanFactory();
 54             //若父類不爲空而且BeanDefinitionMap中全部加載的類不包括beanName,則嘗試在父類工廠去檢測
 55             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 56                 // Not found -> check parent.
 57                 String nameToLookup = originalBeanName(name);
 58                 if (parentBeanFactory instanceof AbstractBeanFactory) {
 59                     return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
 60                             nameToLookup, requiredType, args, typeCheckOnly);
 61                 }
 62                 else if (args != null) {
 63                     // 委託給具備顯示參數args的父工廠,遞歸到BeanFactory中尋找
 64                     return (T) parentBeanFactory.getBean(nameToLookup, args);
 65                 }
 66                 else if (requiredType != null) {
 67                     //委託給標準的父工廠getBean方法
 68                     return parentBeanFactory.getBean(nameToLookup, requiredType);
 69                 }
 70                 else {
 71                     return (T) parentBeanFactory.getBean(nameToLookup);
 72                 }
 73             }
 74 
 75             // 若是不只僅是作類型檢查而是建立bean,在這裏進行記錄
 76             if (!typeCheckOnly) {
 77                 markBeanAsCreated(beanName);
 78             }
 79 
 80             try {
 81     /***************(6)GenericBeanDefinition轉爲RootBeanDefinition **************/
 82                 // 將存儲XML配置文件的GenericBeanDefinition轉換爲RootBeanDefinition,
 83                 // 若是指定BeanName是子Bean的話同時會合並父類的相關屬性
 84                 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 85                 checkMergedBeanDefinition(mbd, beanName, args);
 86     /*********************************(7)尋找依賴 *******************************/
 87                 //獲得該bean所依賴的相關bean
 88                 String[] dependsOn = mbd.getDependsOn();
 89                 // 若存在依賴則須要遞歸實例化依賴的bean
 90                 if (dependsOn != null) {
 91                     for (String dep : dependsOn) {
 92                         if (isDependent(beanName, dep)) {
 93                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 94                                     "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
 95                         }
 96                         // 緩存依賴調用
 97                         registerDependentBean(dep, beanName);
 98                         try {
 99                             getBean(dep);
100                         }
101                         catch (NoSuchBeanDefinitionException ex) {
102                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
103                                     "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
104                         }
105                     }
106                 }
107     /*********************(8)依據scope建立bean(最關鍵的一步) ********************/
108                 //到這裏已經實例化玩依賴的bean了,因此開始實例化mbd自己了
109                 // singleton模式的建立
110                 if (mbd.isSingleton()) {
111                     sharedInstance = getSingleton(beanName, () -> {
112                         try {
113                             return createBean(beanName, mbd, args);
114                         }
115                         catch (BeansException ex) {
116                             // Explicitly remove instance from singleton cache: It might have been put there
117                             // eagerly by the creation process, to allow for circular reference resolution.
118                             // Also remove any beans that received a temporary reference to the bean.
119                             destroySingleton(beanName);
120                             throw ex;
121                         }
122                     });
123                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
124                 }
125 
126                 else if (mbd.isPrototype()) {
127                     // prototype原型模式的建立(new)
128                     Object prototypeInstance = null;
129                     try {
130                         beforePrototypeCreation(beanName);
131                         prototypeInstance = createBean(beanName, mbd, args);
132                     }
133                     finally {
134                         afterPrototypeCreation(beanName);
135                     }
136                     bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
137                 }
138 
139                 else {
140                     // 指定的scope上實例化bean
141                     String scopeName = mbd.getScope();
142                     final Scope scope = this.scopes.get(scopeName);
143                     if (scope == null) {
144                         throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
145                     }
146                     try {
147                         Object scopedInstance = scope.get(beanName, () -> {
148                             beforePrototypeCreation(beanName);
149                             try {
150                                 return createBean(beanName, mbd, args);
151                             }
152                             finally {
153                                 afterPrototypeCreation(beanName);
154                             }
155                         });
156                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
157                     }
158                     catch (IllegalStateException ex) {
159                         throw new BeanCreationException(beanName,
160                                 "Scope '" + scopeName + "' is not active for the current thread; consider " +
161                                 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
162                                 ex);
163                     }
164                 }
165             }
166             catch (BeansException ex) {
167                 cleanupAfterBeanCreationFailure(beanName);
168                 throw ex;
169             }
170         }
171     /*********************************(9)類型轉換 *******************************/
172         // 檢查須要的類型是否符合bean的實際類型
173         if (requiredType != null && !requiredType.isInstance(bean)) {
174             try {
175                 T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
176                 if (convertedBean == null) {
177                     throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
178                 }
179                 return convertedBean;
180             }
181             catch (TypeMismatchException ex) {
182                 if (logger.isTraceEnabled()) {
183                     logger.trace("Failed to convert bean '" + name + "' to required type '" +
184                             ClassUtils.getQualifiedName(requiredType) + "'", ex);
185                 }
186                 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
187             }
188         }
189         return (T) bean;
190     }

上述1-9步在上述代碼中已用分割線隔開,下面依次進行分析:
  (1)轉換對應的beanName轉換對應的 beanName 是根據 getBean(String name) 方法傳入的 name 參數進行的,傳入的 name 並不必定是 beanName,多是別名,也多是 FactoryBean 。因爲 name 的多種可能,Spring會進行對應的轉換。這些轉換包括: 1)去除 FactoryBean 的修飾符,通常就是去除 name 參數的 & 前綴;2)取指定的 alias 所表示的最終 beanName,例如別名 A 指向別名 B,別名 B 指向名稱爲 C 的 bean,則最後返回 C。實際是由org.springframework.beans.factory包中的BeanFactoryUtils類中的函數transformedBeanName()完成此功能。

  (2)嘗試從緩存中加載單例單例在Spring中的同一個容器內只會被建立一次,後續再獲取 bean就直接從單例緩存中獲取了。固然代碼實現上首先進行嘗試從緩存中進行加載,若是不成功再嘗試從 singletonFactories 中加載,最後都不行才判斷是沒有建立過繼而新建並放入緩存。之因此須要從 singletonFactories 中加載,由於在建立單例 bean 的時候會存在依賴注入 的狀況,而在建立依賴 bean 的時候,爲了不循環依賴,Spring中建立 bean 的原則是不等 bean 建立完成就會提早將建立 bean 的 ObjectFactory 曝光加入到緩存中,一旦下一個 bean 建立的時候須要依賴該 bean 時則能夠直接使用 ObjectFactory 做爲依賴進行注入。

  (3)bean的實例化若是從緩存中獲得了 bean 的原始狀態,則須要對 bean 進行實例化。緩存中記錄的只是最原始的 bean 狀態,並非咱們最終想要的 bean。例如:假如咱們須要對工廠 bean 進行處理,那麼這裏獲得的實際上是工廠 bean 的初始狀態,但咱們真正須要的是工廠 bean 中定義的 factory-method方法中返回的 bean,而 getObjectForBeanInstance(sharedInstance, name, beanName, null) 就是完成這項工做。

  (4)原型模式(prototype)的依賴檢查Spring可以嘗試解決的循環依賴問題只有單例模式下,對於原型模式的循環依賴問題Spring是沒有方法解決的。由於在原型模式(prototype)下,若是 A 依賴 B,B 同時又依賴 A,那麼就會出現建立 A 時由於建立依賴 B 而又要建立 A ,由於是多例的,因此會一直循環建立。Spring對於原型模式下的循環依賴會進行檢測,檢測代碼爲 isPrototypeCurrentlyInCreation(beanName) ,若是爲 true,則會拋出異常。

  (5)檢測parentBeanFactory代碼上的邏輯能夠看出,若是從緩存中沒有取到,那麼直接轉到父類工廠上去加載了。由於代碼中的判斷邏輯是:if (parentBeanFactory != null && !containsBeanDefinition(beanName)),前半部分還好,parentBeanFactory 不能爲空,後半部分 !containsBeanDefinition(beanName)意思若是當前的 beanDefinitionMap (XML配置文件)中沒有 beanName 對應的配置,就只能到 parentBeanFactory 中去嘗試下,再遞歸的調用 getBean()方法了。

  (6)GenericBeanDefinition轉爲RootBeanDefinition若是從緩存中獲取不到,同時當前的 beanDefinitionMap 中存在對應 beanName 的配置,咱們就能夠依據包含有XML配置文件信息的 beanDefinition 進行建立 bean 了。從XML配置文件中讀取到的 bean 信息是利用 GenericBeanDefinition 存儲的,可是後面Spring對全部 bean 的後續處理都是針對於 RootBeanDefinition 的,因此須要進行轉換,轉換的同時若是父類 bean 不爲空,則會一併合併父類的屬性。

  (7)尋找依賴由於 bean 的初始化過程當中極可能會用到某些屬性,而某些屬性極可能是動態配置的,而且配置的成功依賴於其餘的 bean,那麼此時應該先加載依賴的 bean。因此在流程中,Spring初始化一個 bean,會先初始化其依賴的全部的其餘 bean。

  (8)依據scope建立beanSpring存在不一樣的 scope,其中默認的是 singleton,可是還有其餘的配置像 prototype、request 等。在這一步中,Spring會根據配置進行採起對應的初始化策略。

  (9)類型轉換待 scope 建立完 bean 成功後,通常能夠直接返回便可。但當傳入 doGetBean 方法中的 requireType 參數不爲空時,意味着咱們對最後返回的 bean 有着類型上的要求。Spring通常經過類型轉換器將第八步建立完成的 bean 轉換爲 requireType 指定的類型。Spring自身提供了一些轉換器,用戶也能夠本身擴輾轉換器來知足需求。通過以上的九個步驟,bean 建立完成,這個時候返回的就是咱們須要的bean。其中第八步最爲關鍵:針對不一樣的 scope 進行 bean 的建立。

 

6、Bean的生命週期

  Spring的IoC容器功能很是強大,負責Spring的Bean的建立和管理等功能。而Spring 的bean是整個Spring應用中很重要的一部分,瞭解Spring Bean的生命週期對咱們瞭解整個spring框架會有很大的幫助。BeanFactory和ApplicationContext是Spring兩種很重要的容器,前者提供了最基本的依賴注入的支持,然後者在繼承前者的基礎進行了功能的拓展,例如增長了事件傳播,資源訪問和國際化的消息訪問等功能。下面介紹ApplicationContext和BeanFactory兩種容器的Bean的生命週期。

  ApplicationContext Bean生命週期:

ApplicationContext Bean生命週期流程ApplicationContext容器中,Bean的生命週期流程如上圖所示,流程大體以下:

  一、首先容器啓動後,會對scope爲singleton且非懶加載的bean進行實例化,

  二、按照Bean定義信息配置信息,注入全部的屬性,

  三、若是Bean實現了BeanNameAware接口,會回調該接口的setBeanName()方法,傳入該Bean的id,此時該Bean就得到了本身在配置文件中的id,

  四、若是Bean實現了BeanFactoryAware接口,會回調該接口的setBeanFactory()方法,傳入該Bean的BeanFactory,這樣該Bean就得到了本身所在的BeanFactory,

  五、若是Bean實現了ApplicationContextAware接口,會回調該接口的setApplicationContext()方法,傳入該Bean的ApplicationContext,這樣該Bean就得到了本身所在的ApplicationContext,

  六、若是有Bean實現了BeanPostProcessor接口,則會回調該接口的postProcessBeforeInitialzation()方法,

  七、若是Bean實現了InitializingBean接口,則會回調該接口的afterPropertiesSet()方法,

  八、若是Bean配置了init-method方法,則會執行init-method配置的方法,

  九、若是有Bean實現了BeanPostProcessor接口,則會回調該接口的postProcessAfterInitialization()方法,

  十、通過流程9以後,就能夠正式使用該Bean了,對於scope爲singleton的Bean,Spring的IoC容器中會緩存一份該bean的實例,而對於scope爲prototype的Bean,每次被調用都會new一個新的對象,其生命週期就交給調用方管理了,再也不是Spring容器進行管理了,

  十一、容器關閉後,若是Bean實現了DisposableBean接口,則會回調該接口的destroy()方法,

  十二、若是Bean配置了destroy-method方法,則會執行destroy-method配置的方法,至此,整個Bean的生命週期結束。

 

  BeanFactory Bean生命週期流程圖:

BeanFactory Bean生命週期流程:

  一、容器尋找Bean的定義信息,並將其實例化。

  二、使用依賴注入,Spring按照Bean定義信息配置Bean的全部屬性。

  三、若是Bean實現了BeanNameAware接口,工廠調用Bean的setBeanName()方法傳遞Bean的id。

  四、若是實現了BeanFactoryAware接口,工廠調用setBeanFactory()方法傳入工廠自身。

  五、若是BeanPostProcessor和Bean關聯,那麼它們的postProcessBeforeInitialization()方法將被調用。(須要手動進行註冊!)

  六、若是Bean實現了InitializingBean接口,則會回調該接口的afterPropertiesSet()方法。

  七、若是Bean指定了init-method方法,就會調用init-method方法。

  八、若是BeanPostProcessor和Bean關聯,那麼它的postProcessAfterInitialization()方法將被調用。(須要手動註冊!)

  九、如今Bean已經能夠使用了。scope爲singleton的Bean緩存在Spring IOC容器中。scope爲prototype的Bean生命週期交給客戶端。

  十、銷燬。若是Bean實現了DisposableBean接口,destory()方法將會被調用。若是配置了destory-method方法,就調用這個方法。

 

BeanFactoty容器中Bean的生命週期與ApplicationContext相比,有以下幾點不一樣:

  一、BeanFactory容器中,不會調用ApplicationContextAware接口的setApplicationContext()方法,

  二、BeanPostProcessor接口的postProcessBeforeInitialzation()方法和postProcessAfterInitialization()方法不會自動調用,必須本身經過代碼手動註冊,

  三、BeanFactory容器啓動的時候,不會去實例化全部Bean,包括全部scope爲singleton且非懶加載的Bean也是同樣,而是在調用的時候去實例化。

 

Bean 實例建立時序圖

 

Bean 對象關係創建流程圖:

 

 

參考:

1. 《Spring源碼深度解析》 郝佳 編著

2.  一天不進步就是退步  博客園

3. weixin_30439131 CSDN博客

4. 等一杯咖啡  CSDN博客

 

博衆家之所長,集羣英之薈萃。遴選各IT領域精品雄文!

歡迎關注「IT架構精選」

相關文章
相關標籤/搜索