天天看點

Spring之IOC控制反轉的了解

Spring IOC簡介

beans和context包是IOC容器的基礎,BeanFactory 提供的進階配置機制,使得管理各種對象成為可能。 ApplicationContext 是BeanFactory的擴充,功能得到了進一步增強,比如更易 與Spring AOP內建、資源處理(國際化處理)、事件傳遞及各種不同應用層的context實作 (如針對web應用的WebApplicationContext)。總之,在實際應用更多會選擇ApplicationContext,原因是ApplicationContext即繼承了BeanFactory的功能,同時又增加的更多支援企業核心内容的支援。

Spring IOC關鍵概念了解

IOC(Inversion of Control):控制反轉,即指擷取對象的方式被反轉了,我們隻需要在applicationContext.xml(Spring的配置檔案)檔案配置中繼資料(即指xml)中的bean指定相應class(類)的全路徑,Spring中的容器(BeanFactory)會負責類對象的建立、配置和管理這些對象及它們之間的依賴關系,而且這些對象和我們通過new Object()的對象沒有差別,這樣最終會達到解耦的目的(即減少代碼之間的依賴);

Bean:在Spring中,那些組成你應用程式的主體(backbone)及由Spring IoC容器所管理的對象,被稱之為bean。 簡單地講,bean就是由Spring容器初始化、裝配及管理的對象,除此之外,bean就與應用程式中的其他對象沒有什麼差別了。 而bean定義以及bean互相間的依賴關系将通過配置中繼資料來描述。

容器:即指Spring IOC容器,BeanFactory是容器的實際代表者,他負責bean對象的建立,配置和容納建立的bean描述并且管理bean;Spring為我們提供了許多易用的BeanFactory實作, XmlBeanFactory就是最常用的一個。該實作将以XML方式描述組成應用的對象以及對象間的依賴關系。XmlBeanFactory類将擷取此XML配置中繼資料,并用它來建構一個完全可配置的系統或應用。

Spring之IOC控制反轉的了解

Spring IOC 容器

中繼資料:我們通常配置的Spring配置xml檔案内容,就是中繼資料;

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

  <bean id="..." class="...">
    <!-- collaborators and configuration for this bean go here -->
  </bean>

  <bean id="..." class="...">
    <!-- collaborators and configuration for this bean go here -->
  </bean>

  <!-- more bean definitions go here -->

</beans>      

注入依賴:

依賴注入(DI)背後的基本原理是對象之間的依賴關系(即一起工作的其它對象)隻會通過以下幾種方式來實作:構造器的參數、工廠方法的參數,或給由構造函數或者工廠方法建立的對象設定屬性。是以,容器的工作就是建立bean時注入那些依賴關系。相對于由bean自己來控制其執行個體化、直接在構造器中指定依賴關系或者類似服務定位器(Service Locator)模式這3種自主要制依賴關系注入的方法來說,控制從根本上發生了倒轉,這也正是控制反轉(Inversion of Control, IoC) 名字的由來。 

Spring的IOC關鍵配置

1.如何定義(建立)一個bean

Spring IoC容器将管理一個或多個bean,這些bean 将通過配置檔案中的bean定義被建立(在XML格式中為<bean/> 元素)。

在容器内部,這些bean定義由BeanDefinition 對象來表示,該定義将包含以下資訊:

  • 全限定類名:這通常就是已定義bean的實際實作類。
  • bean行為的定義,這些定義将決定bean在容器中的行為(作用域、生命周期回調等等)
  • 對其他bean的引用,這些引用bean也可以稱之為協作bean(collaborators) 或依賴bean(dependencies).
  • 建立bean執行個體時的其他配置設定。比如使用bean來定義連接配接池,可以通過屬性或者構 造參數指定連接配接數,以及連接配接池大小限制等。

上述内容直接被翻譯為每個bean定義包含的一組properties。具體的properties屬性參考下面的:Spring官方的翻譯文檔;

2.bean如何執行個體化

從本質上來說,bean定義描述了如何建立一個或多個對象執行個體。當需要的時候, 容器會從bean定義清單中取得一個指定的bean定義,并根據bean定義裡面的配置中繼資料 使用反射機制來建立(或取得)一個實際的對象。

當采用XML描述配置中繼資料時,将通過<bean/>元素的 class屬性來指定執行個體化對象的類型。class 屬性 (對應BeanDefinition執行個體的 Class屬性)通常是必須的(不過也有兩種例外的情形,見 Section 3.2.3.2.3, “使用執行個體工廠方法執行個體化”和 Section 3.6, “bean定義的繼承”)。class屬性主要有兩種用途 :在大多數情況下,容器将直接通過反射調用指定類的構造器來建立bean(這有點類似于 在Java代碼中使用new操作符);在極少數情況下,容器将調用 類的靜态工廠方法來建立bean執行個體,class 屬性将用來指定實際具有靜态工廠方法的類(至于調用靜态工廠 方法建立的對象類型是目前class還是其他的class則無關緊要)。

執行個體化主要有三種方式:用構造器來執行個體化,使用靜态方法執行個體化,使用執行個體工廠來執行個體化;

3.DI-注入依賴(指的就是對象與對象之間的依賴關系通過配置的方式建立) 通過以下幾種方式來實作:構造器的參數、工廠方法的參數,或給由構造函數或者工廠方法建立的對象設定屬性。DI主要有兩種注入方式,即 Setter注入和 構造器注入;

3.1(Setter)首先是一個用XML格式定義的Setter DI例子。相關的XML配置如下:

<bean id="exampleBean" class="examples.ExampleBean">

  <!-- setter injection using the nested <ref/> element -->
  <property name="beanOne"><ref bean="anotherExampleBean"/></property>

  <!-- setter injection using the neater 'ref' attribute -->
  <property name="beanTwo" ref="yetAnotherBean"/>
  <property name="integerProperty" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>      
public class ExampleBean {

    private AnotherBean beanOne;
    private YetAnotherBean beanTwo;
    private int i;

    public void setBeanOne(AnotherBean beanOne) {
        this.beanOne = beanOne;
    }

    public void setBeanTwo(YetAnotherBean beanTwo) {
        this.beanTwo = beanTwo;
    }

    public void setIntegerProperty(int i) {
        this.i = i;
    }    
}      

3.2(構造器參數的方式)正如你所看到的,bean類中的setter方法與xml檔案中配置的屬性是一一對應的。接着是構造器注入的例子:

<bean id="exampleBean" class="examples.ExampleBean">

  <!-- constructor injection using the nested <ref/> element -->
  <constructor-arg>
    <ref bean="anotherExampleBean"/>
  </constructor-arg>
  
  <!-- constructor injection using the neater 'ref' attribute -->
  <constructor-arg ref="yetAnotherBean"/>
  
  <constructor-arg type="int" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>      
public class ExampleBean {

    private AnotherBean beanOne;
    private YetAnotherBean beanTwo;
    private int i;
    
    public ExampleBean(
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
        this.beanOne = anotherBean;
        this.beanTwo = yetAnotherBean;
        this.i = i;
    }
}      

4.Bean的生命周期回調 在Bean的建立之前或銷毀的時候,我們可能做一些初始化處理或者釋放資源的操作;

Spring提供了幾個标志接口(marker interface),這些接口用來改變容器中bean的行為;它們包括InitializingBean和DisposableBean。實作這兩個接口的bean在初始化和析構時容器會調用前者的afterPropertiesSet()方法,以及後者的destroy()方法。 

Spring在内部使用BeanPostProcessor實作來處理它能找到的任何标志接口并調用相應的方法。如果你需要自定義特性或者生命周期行為,你可以實作自己的 BeanPostProcessor。關于這方面更多的内容可以看Section 3.7, “容器擴充點”。

以上僅僅是我基于學習Spring官方翻譯文檔的一些關鍵内容記錄,具體的學習請參考官方翻譯文檔

參考:

Spring官方翻譯文檔:http://shouce.jb51.net/spring/beans.html