spring bean生命週期學習

第一章 IoC容器

IoC定義:Inverse of Control 控制反轉。將new接口實現類的權利交到第三方類(導演類)中。導演類負責實例化接口的實現類,然後注入到依賴類中。

類加載器和反射。通過反射的方式可以將配置文件中定義字符串變成類的實例(先通過全名限定,利用類加載器加載類進jvm),然後根據依賴關係注入到其他類中。

資源訪問接口
    ——Resource接口的不同實現類負責從不同類型資源文件中加載資源。ResourceLoader資源加載器及其實現類PathMatchingResourcePatternResolver負責根據資源地址前綴和路徑通配符加載資源。
    ——有了上述接口,spring容器將可以方便的加載配置文件中定義的bean信息,從而實現控制反轉。

IoC容器:BeanFactory和ApplicationContext   ApplicationContext基於BeanFactory兩個容器在啓動的時候必須初始化日誌框架例如:log4j。不然spring啓動將出錯。

BeanFactory
    ——BeanFactory作爲IoC容器的核心接口,通過不斷的擴展性形成了一套繼承體系。這套體系可以讓開發者從不同層面使用容器。
    ——ConfigurableBeanFactory等接口可以爲容器添加定製化的功能。例如:在bean生產的過程中添加一系列處理器,以增強bean的實例化過程。
    ——BeanFactory目前的實現類只有DefaultListableBeanFactory 而 XmlBeanFactory已經被廢棄。
    ——XmlBeanDefinitonReader負責將配置文件的bean定義解析爲BeanDefiniton類,爲BeanFactory提供信息。ClassPathXmlApplicationContext中已經具備該能力。
    ——AnnotationConfigApplicationContext具備從java配置類中啓動的能力。WebApplicationContext具備從web根路徑啓動的能力。WebApplicationContext中需引用ServletContext,同時自身也作爲ServletContext屬性,通過ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE鍵被引用
    ——Web環境中初始化WebApplicationContext有2中方式:自啓動Servlet和ContextLoaderListen。低版本Servlet不支持監聽的方式啓動。啓動只需在web中配置即可。
 
BeanFactory的生命週期
    1. 生命週期過程: getBean()過程
        ——調用postProcessBeforeInstatiation()方法   1
        ——調用bean的構造器
        ——調用postProcessAfterInstantiation()方法   1
        ——調用postProcessProptertyValues()方法      1
    ——調用bean的屬性器設置屬性(注入配置文件中定義的屬性依賴)
    ——調用setBeanName()方法                2
        ——調用setBeanFacotry()方法              2
        ——調用postProcessBeforeInitialization()方法 3
        ——調用afterPropertiesSet()方法          2
        ——調用init-method配置的初始化方法
        ——調用postProcessAfterInitialization()方法  3
        ——單例放入容器的緩衝池中。prototype交給調用者
        ——調用destroy()方法                  2
        ——調用destroy-method配置的銷燬方法    
            ——整個生命週期中:1爲容器級的處理器(InstantiationAwareBeanPostProcessor接口),負責處理所有bean的共性問題;2爲bean級的處理器,定義在bean自身類中(通過實現BeanNameAware、BeanFactoryAware、InitializingBean、DisposableBean接口);3爲容器級的處理器(BeanPostProcessor接口)。
          ——其中InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口。通過ConfigurableBeanFactory.addBeanPostProcess()方法可以將自定義的處理器加入到beanFactory中。
             ——容器在創建的過程中會檢查這些接口,然後做相應處理。
        ——從上述生命週期過程可以看出,核心過程爲調用bean的構造器,屬性器,初始化方法,銷燬方法的過程。各處理器爲spring框架生命週期接口提供的額外控制。但使用spring不應對應用程序類做任何限制。所以一般不會註冊這些處理器。AOP和註解例外。

ApplicationContextd的生命週期
    ——其生命週期與BeanFactory基本一致。
    ——在ApplicationContext啓動的時候(<bean>被解析爲BeanDefiniton時)可以註冊BeanFactoryPostProcessor處理器,並調用postProcessBeanFactory()方法以對配置文件進行處理。該處理器可以直接在配置文件中聲明實現了對應接口的bean來註冊。


第二章:在IoC容器中裝配Bean
Bean定義註冊表:將配置中的bean定義加載進spring,通過id和BeanDefiniton描述。多個BeanDefinition形成了註冊表

基於XML的配置
    ——spring2.0以後採用Schema格式的配置
    ——xmlns爲默認的命名空間 一般爲bean
    ——xmlsn:aop爲aop指定命名空間,aop爲命名空間的別名
    ——xmlns:xsi爲xsi指定命名空間,然後可以通過xsi爲所有命名空間指定xsi文件url
    ——xsi:schemaLocation通過xsi別名配置各命名空間的schema文件。

Bean的基本配置
    ——通過id和name爲Bean命名,id全局唯一、不含特殊字符。name例外,但是同名將覆蓋。
    ——依賴注入
        ——屬性注入:配置<property name=><value></省略></>將通過反射尋找setXXX()方法注入。屬性名前兩個字母要麼全大寫要麼全小寫。    
        ——構造器注入:<construction-arg index= type= ref=><value></></>多相似構造器下使用index和type唯一確定。ref引用其他bean
    ——工廠方法注入:<bean factory-bean="" factory-method=""/> 需先聲明factory-bean這個Bean。
    ——靜態工廠方法注入 <bean class="" factory-method="">
    ——<value>標籤注入字面值 <![CDATA[...]]>讓XML將裏面字符當普通字符處理。沒有值則爲""字符串
    ——<bean/>將在屬性中注入一個bean
    ——<ref parent="">引用父容器中的bean
    ——<null/>將注入Null
    ——<property name="class.property...">可以配置級聯屬性,不過必須在當前類裏面有一個class的實例。
    ——<property name=""><list><value></></></>可以爲list直接注入值。同理<set>也是一樣,不過類中必須先有一個實例化的對象。
    ——<property name=""><list><entry><key><value></></><value></></></></>爲map注入值。
    ——<prperty name=""><props><prop key="">sadf</><prop></></>方式爲properties注入。只能注入字符串類型。
    ——通過util命名空間配置集合類型的bean
    ——<utils:list id="" list-class="java.util.LinkedList"><value></></util:list> map類型爲<entry key="" value=""/><entry />
    ——使用p命名空間
    ——原來的使用property標籤可以直接改爲 p:name="小明" p:car-ref="car"設置屬性和引用。


第三章:ApplicationContext

初始化步驟
    1. 初始化BeanFactory ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    2. 調用工廠後處理器BeanFactoryPostProcessor 在BeanDefinition中找出實現此接口的Bean用來對BeanDefinition中未完成的Bean進行加工.
    3. 註冊bean後處理器 BeanPostProcess用於對bean實例化進行加工
    4. 初始化消息源
    5. 初始化應用上下文事件廣播器
    6. 初始化其他特殊的Bean   onFresh()
    7. 註冊事件監聽器
    8. 初始化所有單實例的Bean,使用懶加載模式的Bean除外
    9. 完成刷新併發布容器刷新事件。

BeanDefinition: 配置文件中<bean>標籤解析後生成的對象,被註冊到BeanDefinitionRegistry中。初步生成的BeanDefinition可能只是半成品,需要BeanFactoryPostProcessor對其進行加工。
來解析佔位符爲最終的實際值。

InstantialtionStrategy 通過不同策略實例化bean, 尚未設置屬性

BeanWrapper 爲Bean設置屬性。主要通過屬性編輯器來設置屬性,通過BeanWrapper接口進行訪問。


屬性編輯器:
——PropertyEditorRegistrySupport爲常見的類型提供了默認的屬性編輯器。 註冊屬性編輯器:defaulEditors.put(char.class, new CharacterEditor(false));

——如果需要對複合類型進行轉換需要自定義的屬性編輯器。可以通過擴展PropertyEditorSupport類來實現自己的屬性編輯器(覆蓋 void setAsText(String text) 定義自定義解析器,然後調用父類setValue()設置轉換後的屬性),然後添加到註冊map中。
CustomerEditorConfigurer類實現了工廠後處理器,將在spring初始化的時候,自動調用。所以只需在其customEditors屬性中,加入自定義的編輯器類即可。
<bean class= "org.springframework.beans.factory.config.CustomEditorConfigurer">
    <property name = "customEditors">
       <map>
             <entry key = "com.xx.Xxx" value= "com.xxx.xxx.CustomXxxEditor">          
             </entry>
       </map>
    </property>
</bean>
這樣就可以爲某個類型註冊一個屬性編輯器,直接在配置文件中按照自定義格式設置字面值,屬性編輯器會解析成對應複合類型。
  
——使用外部屬性文件: PropertyPlaceholderConfigurer在對屬性進行轉換的時候,會去外部文件尋找值進行佔位符替換。
該類實現了BeanFactoryPostProcessor接口在spring容器初始化的時候將自定調用(postProcessBeanFactory方法,在該方法中調用convertProperty方法設置屬性值。)以完善BeanDefiniton對象的內容。
<bean class = "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
      p:location = "classpath:com/smart/placeholder/jdbc.properties">
        p:fileEncoding = "utf-8" /> 可在該類中指定外部屬性文件的地址和編碼方式
或者:
<context:property-placeholder location="classpath:com.smart.jdbc.properties">

在其父類中PropertyResourceConfigurer類中,convertProperty(propertyName, propertyValue)用於在屬性使用之前對屬性值進行轉換處理。可以用來對密碼等屬性進行加解密。

——應用其他bean的值:
#{beanName.beanproperty}可以直接引用其他bean中的屬性值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章