Spring學習筆記二: Bean裝配及生命週期

衣舞晨風發表於2016-07-14

bean被載入到容器中時,它的生命週期就開始了:

  1. 容器尋找bean的定義資訊並例項化。
  2. 使用依賴注入,spring按bean定義資訊配置bean的所有屬性。
  3. 若bean實現了BeanNameAware介面,工廠呼叫Bean的setBeanName()方法傳遞bean的ID。
  4. 若bean實現了BeanFactoryAware介面,工廠呼叫setBeanFactory()方法傳入工廠自身。
  5. 若BeanPostProcessor(bean後置處理器)和bean關聯,則它們的
    postProcessBeforeInitialization()方法被呼叫。
  6. 若bean指定了ini-method方法、,它將被呼叫。
  7. 最後,若有BeanPostProcessor和bean關聯,則它們的postProcessAfterInitialization()方法被呼叫。

將bean從工廠中刪掉有兩種方法:

  1. 若bean實現了DisposableBean介面,distroy()方法被呼叫。
  2. 如果指定了定製的銷燬方法,就呼叫這個方法。

Bean在Spring Bean應用上下文中的生命週期:
這裡寫圖片描述

Bean在Spring Bean工廠中的生命週期:
這裡寫圖片描述

Spring bean生命週期demo 原始碼下載

基本裝配:

在spring容器內拼湊bean叫做裝配。裝配bean的時候,需要告訴容器哪些bean以及容器如何使用依賴注入將它們配合在一起。

  1. 使用XML裝配
    xml是最常見的spring應用系統配置源。幾種spring容器都支援使用xml裝配bean。

包括:

  1. XmlBeanFactory:呼叫ClassPathResource載入上下文定義檔案(比如applicationContext.xml)。

  2. ClassPathXmlApplicationContext:從類路徑載入上下文定義檔案。

  3. XmlWebApplicationContext:從web應用上下文中載入定義檔案。

上下文定義檔案的根元素是.有多個子元素。每個元素定義了一個bean如何被裝配到spring容器中。

<beans>
       <bean id="foo" class="...Foo"/>
       <bean id="bar" class="...Bar"/>
</beans>

新增一個bean

對bean的最基本的配置包括bean的ID和他的全稱類名。

<bean id="foo" class="...Foo"/>

基本裝配-scope

prototype、singleton、request 、session、global-session
spring中的bean預設情況下是單例模式。始終返回一個例項。若想返回不同的例項的話需要定義成原型模式。
bean的singleton屬性告訴上下文該bean是否為單例的。預設為true。若為false的話,為原型bean。

<bean id="foo" class="...Foo" singleton="false"/>

例項化與銷燬

1、spring例項化bean或銷燬bean時,有時需要作一些處理工作,因此 spring可以在建立和拆卸bean的時候呼叫bean的兩個生命週期方法。

  <bean class="Foo" init-method destory-method>
    @PostConstruct
    public void ini(){
        // do something

    }
    @PreDestroy
    public void destroy(){
        // do something
    }

2、 Spring也提供了兩個介面來實現相同的功能:
InitializingBean和DisposableBean.
InitializingBean介面提供了一個afterPropertiesSet()方法。
DisposableBean介面提供了destroy().

不推薦使用該介面,它將你的bean和springAPI邦定在一起。

通過set方法注入依賴

元素的子元素指明瞭使用它們的set方法來注入。可以注入任何東西,從基本型別到集合類,甚至是應用系統的bean。
1、簡單bean配置
配置bean的簡單屬性,基本資料型別和string。

<bean id="foo" class="...Foo">
        <property name="name">
              <value>tom</value>
        </property>  
  </bean>

2、引用其它bean

這裡寫圖片描述

3、內部bean

<bean id="foo" class="...Foo">
        <property name="bar">
              <bean class="...Bar">
        </property>  
  </bean>

這種方式的缺點是你無法在其它地方重用這個bar例項,原因是它是專門為foo而用。

基本裝配:

  1. 繼承
  2. 繼承配置
  3. 覆蓋父 Bean配置

可以設定 的abstract 屬性為 true, Spring 不會例項化該Bean

<bean  id="gradate" parent="student"  class=“...Gradate">

裝配集合

若bean的屬性是集合型別,按如下處理:
1、裝配List和陣列:

  <property name="barlist">
       <list>
           <value>bar1</value>
           <ref bean="bar2"/>
       </list>
  </property>

2、裝配set:

<property name="barlist">
       <set>
        <ref bean="bar2"/>
       </set>
  </property>

set使用方法和list一樣,不同的是物件被裝配到set中,而list是裝配到List或陣列中裝配。
3、裝配map:

<property name="barlist">
       <map>
           <entry key="key1" value="bar1" />
           <entry key="key2 value-ref="xxx" />
      </map>
  </property>

key值必須是string的,key-ref可以是其他bean
4、裝配Properties:

<property name="barlist">
       <props>
           <prop key="key1">bar1</prop>
           <prop key="key2">bar2</prop>
       </props>
  </property>

若bean的屬性是集合型別,按如下處理:
1、設定null:

<property name="barlist">
         <null/>
  </property>

2、Set注入的替代:
set注入是一種直接方式,也可通過建構函式設定一些屬性值。

<constructor-arg index="0" type="java.lang.String" value="小明" />
<constructor-arg index="1" type="int" value="20"/>
<constructor-arg  index="2" type="double" value="34.5" />

set注入的缺點是無法清晰表達哪些屬性是必須的,哪些是可選的,構造注入的優勢是通過構造強制依賴關係,不可能例項化不完全的或無法使用的bean。

如果屬性是類型別,則使用 ref=“”

自動裝配

<bean id="foo" class="...Foo" autowire="autowire type">

有四種自動裝配型別:

  1. byName尋找和屬性名相同的bean,若找不到,則裝不上。
  2. byType:尋找和屬性型別相同的bean,找不到,裝不上,找到多個拋異常。

  3. constructor:查詢和bean的構造引數一致的一個或
    多個bean,若找不到或找到多個,拋異常。按照引數的型別裝配

  4. autodetect: (3)和(2)之間選一個方式。不確定性的處理與(3)和(2)一致。

  5. no : 不自動裝配,這是autowrite的預設值.

  6. defualt : 這個需要在
<beans defualt-autorwire=“指定” />

使用byType和constructor自動裝配時,若找到多個符合條件的bean,會報異常,因此最好的方式是不用自動組裝。

混合使用手動和自動組裝

 <bean id="bar" class="...Bar" autowire="byName">
   <property name="cousedao">
       <ref bean="somebean" />
   </property>
 </bean>

預設自動組裝

預設不是自動組裝。
通過:

<beans default-autowire="byName">

可將bean設定為自動組裝。

spring2.5提供了<context:annotation-config/>配置.
該配置可啟用在類中探測到的各種註解,

  • @Required
  • @Autowire
  • @PostConstrct
  • @PreDestroy
  • @Resource
  • @EJB
  • @PersistenceContext
  • @WebServiceRef

等等,也可以選擇為這些註解啟用單獨的後處理器.
例如:

  • AutowiredAnnotationBeanPostProcessor(處理自動裝配)
  • CommonAnnotationBeanPostProcessor(生命週期等)

注意:該標記不能啟用事務處理.需要使用tx:annotation-driven

使用spring的特殊bean

讓spring特殊對待這些bean。使它們可以:

  1. 通過配置後加工bean,涉及到Bean和Bean工廠生命週期。
  2. 改變依賴注入,將字串轉換成其它型別。
  3. 從屬性文字裝載資訊,包括資訊國際化。
  4. 監聽並處理其它bean及spring釋出的系統訊息。
  5. 知道自己在spring中的唯一表識。

對bean進行後處理

BeanPostProcessor介面提供機會來修改bean。

public interface BeanPostProcessor{
         //Bean初始化(呼叫afterPropertiesSet()以及Bean的指
         //定initmethod方法)之前被呼叫。
         Object postProcessorBeforeInitialation(…);
         //在初始化之後馬上呼叫
         Object postProcessorAfterInitialization(…);
   }

註冊後處理Bean

如果使用的是Bean工廠,需要呼叫工廠的addBeanPostProcessor()來註冊.

factory.addBeanPostProcessor(…);

如果使用的是上下文同其他Bean一樣:

<bean id="" class="……" />

BeanPostProcessor在bean載入後,對bean進行一些後處理工作。而BeanFactoryPostProcessor在bean工廠載入所有bean的定義後,例項化bean之前,對Bean工廠做一些後處理工作。

 public interface BeanFactoryPostProcessor{
         public void postProcessorBeanFactory(…);
    }

如果使用的是應用上下文不需要將他註冊為Bean工廠後處理器。上下文會自動註冊它。按照正常的Bean宣告即可。

本文部分內容整理自網路
作者:jiankunking 出處:http://blog.csdn.net/jiankunking

相關文章