天天看點

Spring的IoC容器

  使用Spring的IoC容器

3.1 BeanFactory和ApplicationContext的介紹

<b>3.1.1</b><b>BeanFactory</b><b>介紹 </b>BeanFactory是一個類工廠,但它和傳統的類工廠不同,傳統的類工廠僅生成一個類的對象,或幾個實作某一相同接口類的對象。而BeanFactory是通用的工廠,他可以建立和管理各種類的對象。這些可被建立和管理的對象本身沒有什麼特别之處,僅是一個簡單的POJO,Spring稱這些被建立和被管理的Java對象為Bean。我們知道JavaBean是要滿足一定規範的,如必須提供一個預設不帶參的構造函數、不依賴于某一特定的容器等,但Spring中所說的Bean比JavaBean更寬泛一些,是以不需要額外服務支援的POJO都可以是Bean。

Spring為BeanFactory提供了多種實作,最常用的是XmlBeanFactory。我們該如何獲得一個XmlBeanFactory呢?

代碼清單1

Resource resource = new FileSystemResource("beans.xml"); 

BeanFactory factory = new XmlBeanFactory(resource); 

或 

ClassPathResource resource = new ClassPathResource("beans.xml"); 

BeanFactory factory = new XmlBeanFactory(resource);

代碼清單1中我們通過FileSystemResource和ClassPathResource都獲得了XmlBeanFactory。但是我們有了XmlBeanFactory對象又能幹什麼用呢?

代碼清單2

<b>    public</b> <b>class</b> Foo {

        <b>private</b> String name;

        <b>public</b> <b>void</b> setName(String name) {

           <b>this</b>.name = name;

        }

        <b>public</b> String toStirng(){

           <b>return</b> "Foo Name is :" + <b>this</b>.name;

}

&lt;?xml version="1.0" encoding="UTF-8"?&gt;

&lt;beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="

           [url]http://www.springframework.org/schema/beans[/url] [url]http://www.springframework.org/schema/beans/spring-beans-2.5.xsd[/url]

           [url]http://www.springframework.org/schema/context[/url] [url]http://www.springframework.org/schema/context/spring-context-2.5.xsd[/url]"&gt;

    &lt;bean id="foo" class="com.tony.test.Foo"&gt;

       &lt;property name="name" value="Foo"/&gt;

    &lt;/bean&gt;

&lt;/beans&gt;

<b>import</b> org.springframework.beans.factory.BeanFactory;

<b>import</b> org.springframework.beans.factory.xml.XmlBeanFactory;

<b>import</b> org.springframework.core.io.ClassPathResource;

<b>public</b> <b>class</b> Test {

    <b>public</b> <b>static</b> <b>void</b> main(String[] args) {

       //定義Spring配置檔案

       ClassPathResource resource = <b>new</b>

                     ClassPathResource("spring-config-beans.xml");

       //執行個體化BeanFactory

       BeanFactory factory = <b>new</b> XmlBeanFactory(resource);

        //根據配置檔案中的id獲得Bean

       Foo foo = (Foo) factory.getBean("foo");   

        System.out.println(foo.toStirng());   

    }  

運作結果 Foo Name is :Foo

代碼清單2中我們首先定義了一個很普通的java類Foo.java然後在Spring配置檔案中将其配置,關鍵的是我們的Test.java類我們首先執行個體化了ClassPathResource對象,在執行個體化時我們已經告訴了它Spring配置檔案的名稱,執行個體化BeanFactory後我們通過factory.getBean就可以獲得由Spring管理的Bean了。我們驚奇的發現Spring竟然幫我們把Foo對象中name屬性的資料裝配進去了。

<b>3.1.2</b><b> A</b><b>pplicationContext </b><b>介紹</b><b> </b>如果說BeanFactory是Spring的心髒,那麼ApplicationContext就是Spring的五髒六腑和軀幹四肢了。ApplicationContext接口由BeanFactory派生而來,提供了更多面向實際應用的功能,在BeanFactory中,很多功能需要以程式設計的方式進行操作,而在ApplicationContext中則可以通過配置的方式進行控制。簡而言之,<code>BeanFactory</code>提供了配制架構及基本功能,而<code>ApplicationContext</code>則增加了更多支援企業核心内容的功能。<code>ApplicationContext</code>完全由<code>BeanFactory</code>擴充而來,因而<code>BeanFactory</code>所具備的能力和行為也适用于<code>ApplicationContext</code>。<b></b>

<b>3.2 Bean</b><b>的基本配置</b>

       每個bean都有一個或多個id(或稱之為辨別符或名稱,在術語上可以理  解成    一回事)。這些id在目前IoC容器中必須唯一。如果一個bean有多   個id,      那麼其他的id在本質上将被認為是别名。

    當使用基于XML的配置中繼資料時,将通過<code>id</code>或<code>name</code>屬性來指定bean辨別        符。    <code>id</code>屬性具有唯一性,而且是一個真正的XML ID屬性,是以其他xml    元素在引用該id時,可以利用XML解析器的驗證功能。通常情況下最好為    bean指定一個id。盡管XML規範規定了XML ID命名的有效字元,但是bean  辨別符的定義不受該限制,因為除了使用指定的XML字元來作為id,還可以    為bean指定别名,要實作這一點可以在<code>name</code>屬性中使用逗号、冒号或者空  格将多個id分隔。

    值得注意的是,為一個bean提供一個name并不是必須的,如果沒有指定,  那麼容器将為其生成一個惟一的name。

&lt;bean id="foo" class="com.tony.test.Foo"/&gt;

一般情況下,SpringIoC容器中的一個Bean即對應配置檔案中的一個&lt;bean&gt;,這種鏡像性的對應關系很容易了解。其中id為這個Bean的名稱,通過容器的getBean(“foo”)即可擷取對應的Bean,在容器中起到定位查找的作用,是外部程式和SpringIoC容器進行通信的橋梁。Class屬性指定了Bean對應的實作類。

<b>3.3 </b><b>依賴注入</b>

Spring支援兩種依賴注入方式,分别是屬性注入和構造函數注入。。

<b>3.3.1</b><b>屬性注入</b>

屬性注入即通過setXxx()方法注入Bean的屬性值或依賴對象,由于屬性注入方式具有可選擇性和靈活性高的優點,是以屬性注入是實際應用中最常用的注入方式。

Foo類中定義了一個屬性name,并提供了對應的Setter方法,我們配置了一個Bean,并為該Bean的name屬性提供了屬性值。具體來說,Bean的每一個屬性對應一個&lt;property&gt;标簽,name為屬性的名稱,在Bean實作類中擁有與其的對應的Setter方法name對應setName()方法。

<b>3.3.2</b><b>構造函數注入</b><b></b>

構造函數注入是除屬性注入之外的另一種常用注入方式,它保證一些必要的屬性在Bean執行個體化時就得到設定,它保證了Bean執行個體在執行個體化後就可以使用。

        <b>private</b> <b>int</b> age;

        <b>public</b> Foo(String name,<b>int</b> age){

           <b>this</b>.age = age;

       &lt;constructor-arg type="int"&gt;

           &lt;value&gt;20&lt;/value&gt;

       &lt;/constructor-arg&gt;

       &lt;constructor-arg type="java.lang.String"&gt;

           &lt;value&gt;Foo&lt;/value&gt;

&lt;/bean&gt;

代碼清單1中我們定義了一個構造函數,接受一個String類型的入參,配置檔案中我們配别通過&lt;constructor-arg&gt;元素中定義了type類型為java.lang.String和int的兩個元素,Spring會通過type類型來對構造函數進行注入,是以我們在配置檔案和構造函數入參順序不同的情況下還是可以成功注入。但是我們對于多個構造函數并且類型都一樣的時候我們改怎麼辦呢?

&lt;bean id="foo" class="com.tony.test.Foo"&gt;

       &lt;constructor-arg index="0" value="Foo"/&gt;

       &lt;constructor-arg index="1" value="20"/&gt;

隻要修改配置檔案中&lt;constructor-arg&gt;元素把type屬性改為index并且指定參數的索引就可一了,這裡一定要注意索引是從0開始的。

3.4 <b>Bean</b><b>的作用域</b><b></b>

在配置檔案中定義Bean時,使用者不單可以配置Bean的屬性值以及互相之間的依賴關系,還可以定義Bean的作用域。作用域将對Bean的生命周期和建立方式産生影響。在低版本的Spring中,僅有兩個作用域:singleton和prototype,在Spring2.0中,針對WebApplicationContext新增加了3個作用域。

<b>singleton</b> &lt;bean id="foo" class="…" scope="<b>singleton</b>"/&gt;

    在SpringIoC容器中僅存在一個Bean執行個體,Bean以單執行個體的方式存在。

<b>prototype</b> &lt;bean id="foo" class="…" scope="<b>prototype</b>"/&gt;

    每次從容器中調用Bean時,都傳回一個新的執行個體,即每次調用getBean時,相當于執行newXxxBean的操作。

<b>request</b> &lt;bean id="foo" class="…" scope="<b>request</b>"/&gt;

       每次HTTP請求都會建立一個新的Bean。該作用域僅适用于WebApplicationContext環境。

<b>session </b> &lt;bean id="foo" class="…" scope="<b>session</b>"/&gt;<b></b>

       同一個HTTPSession共享一個Bean,不同HTTPSession使用不同的Bean。該作用域僅适用于WebApplicationContext環境。

<b>globalSession</b> <b> </b> &lt;bean id="foo" class="…" scope="<b>globalSession</b>"/&gt;

       同一個全局Session共享一個Bean,一般用于Protlet應用環境。該作用域僅适用于WebApplicationContext環境。

我的其它Spring文章,也許會對您有幫助

<a href="http://tonyaction.blog.51cto.com/227462/84008" target="_blank">Spring的任務排程和郵件發送</a>

<a href="http://tonyaction.blog.51cto.com/227462/84178" target="_blank">Spring應用的單元測試</a>

<a href="http://tonyaction.blog.51cto.com/227462/84724" target="_blank">Spring的資料庫支援</a>

<a href="http://tonyaction.blog.51cto.com/227462/84893" target="_blank">Spring的MVC架構</a>

<a href="http://tonyaction.blog.51cto.com/227462/85159" target="_blank">Spring的IoC容器</a>

<a href="http://tonyaction.blog.51cto.com/227462/85504" target="_blank">Spring對AOP的支援</a>

<a href="http://tonyaction.blog.51cto.com/227462/83874" target="_blank">Spring2.5注釋驅動與基于注釋的MVC</a>

本文轉自 tony_action 51CTO部落格,原文連結:http://blog.51cto.com/tonyaction/85159,如需轉載請自行聯系原作者

上一篇: 留言回複!
下一篇: Sed指令總彙