Spring的IoC容器

Spring是一個輕量級的Java開發框架,其提供的兩大基礎功能爲IoC和AOP,其中IoC爲依賴反轉(Inversion of Control)。IOC容器的基本理念就是「爲別人服務」,那爲別人服務什麼呢?其中最重要就是業務對象的構建管理和業務對象之間的依賴綁定。java

  • 業務對象的構建管理:業務場景中,無需關心業務對象如何建立、如何管理,在須要時只需獲取便可。業務對象的構建管理交給IoC容器,避免這部分代碼對業務邏輯的侵染。
  • 業務對象之間的依賴綁定:IoC容器須要先了解業務對象之間的依賴關係,這樣依據以前業務對象的構建管理就能夠對外提供IoC服務,保證每一個業務對象在使用時處於就緒狀態。

IoC容器管理業務對象,首先須要知道業務對象之間的依賴關係,如下有幾種方式告訴IoC容器其管理的對象之間的綁定關係:spring

  • 能夠經過簡單的文本方式記錄被注入對象和其依賴對象的對應關係。
  • 使用描述性更強的XML文件格式記錄對象之間的對應關係。
  • 還能夠經過編寫代碼的方式(調用IoC容器提供的對應API)設置對象之間的關係。
  • ...

注意:無論是什麼方式來告知IoC容器對象之間的綁定關係,最終都是須要經過編碼方式來將這些信息"寫入"到IoC容器中的。session

一個XML配置方式的示例:框架

<!-- 配置bean,屬性配置方式 -->
<bean id="helloWorld"  class="com.luo.testspring.HelloWorld" scope="singleton">
    <property name="name" value="spring"/>
</bean>

 

Spring的IoC容器提供兩種基本的容器類型:BeanFactory和ApplicationContext。測試

  • BeanFactory:基礎類型IoC容器,提供基本的容器服務,若是沒有特殊指定,採用延遲初始化策略,也就是當客戶端須要容器中某個對象時,纔對該受管理的對象初始化及其依賴注入操做。因此,相對來講,BeanFactory容器啓動較快,所需資源有限,對於資源有限,而且功能要求不嚴格的場景,使用BeanFactory容器是比較合適的。
  • ApplicationContext:ApplicationContext是在BeanFactory基礎之上構建的,是一個比較高級的容器,除了擁有BeanFactory的所有功能外,也提供其餘高級特性,好比事件發佈、國際化信息支持等。ApplicationContext所管理的對象,默認ApplicationContext啓動以後所有初始化並綁定完成,因此其啓動較慢,佔用資源較多。在系統資源充足,並須要提供較多功能的使用場景,ApplicationContext是一個不錯的選擇。

 

BeanFactory使用示例(XML配置方式):this

/* HelloWolrd類,待依賴注入的類 */
public class HelloWorld {
    private String name;

    public HelloWorld() {
    }

    public HelloWorld(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void hello() {
        System.out.println("hello: " + this.name);
    }
}
<!-- springConfig.xml配置文件Bean配置 -->

<!-- 配置bean,屬性配置方式 -->
<bean id="helloWorld"  class="com.luo.testspring.HelloWorld" scope="singleton">
    <property name="name" value="spring"/>
</bean>

<!-- 經過構造方法配置bean屬性 -->
<bean id="helloWorld2" class="com.luo.testspring.HelloWorld">
    <constructor-arg value="spring2" index="0"></constructor-arg>
</bean>

<bean id="helloWorld3" class="com.luo.testspring.HelloWorld">
    <property name="name">
        <bean class="java.lang.String">
            <constructor-arg value="spring3"/>
        </bean>
    </property>
</bean>
/* 測試代碼 */
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("springConfig.xml"));

HelloWorld helloWorld = (HelloWorld) factory.getBean("helloWorld");
helloWorld.hello();

HelloWorld helloWorld2 = factory.getBean("helloWorld2", HelloWorld.class);
helloWorld2.hello();

HelloWorld helloWorld3 = factory.getBean("helloWorld3", HelloWorld.class);
helloWorld3.hello();

 

ApplicationContext使用示例(XML配置方式):編碼

/* 測試代碼 */
HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");
helloWorld.hello();

HelloWorld helloWorld2 = ctx.getBean("helloWorld", HelloWorld.class);
helloWorld2.hello();

HelloWorld helloWorld3 = ctx.getBean("helloWorld3", HelloWorld.class);
helloWorld3.hello();

 

依賴注入的3種方式spa

  • 構造方法注入:調用被注入對象的構造方然注入,優勢是對象在構造完成就進入了就緒狀態。
  • 屬性注入:調用被注入對象的setter/getter方法。
  • 接口注入:如今不提倡的一種方式,由於它強制被注入對象實現沒必要要的接口,帶有侵入性。

 

spring的bean配置(XML配置方式)prototype

屬性注入即經過 setter 方法注入Bean 的屬性值或依賴的對象,使用 <property> 元素, 使用 name 屬性指定 Bean 的屬性名稱,value 屬性或 <value> 子節點指定屬性值,屬性注入是實際應用中最經常使用的注入方式。屬性注入Bean類須有一個默認的構造方法。3d

<!-- Hello類中有一個String類型的msg屬性 -->
<bean id="hello" class="com.luoxn28.Hello">
    <property name="msg" value="luoxn28"/>
</bean>

經過構造方法注入Bean 的屬性值或依賴的對象,它保證了 Bean 實例在實例化後就可使用,構造器注入在 <constructor-arg> 元素裏聲明屬性。

<bean id="msg" class="java.lang.String">
    <constructor-arg value="string"/>
</bean>
<!-- 按照索引匹配入參 -->
<bean id="car" class="com.luoxn28.Car">
    <constructor-arg value="比亞迪" index="0"/>
    <constructor-arg value="中國製造" index="1"/>
    <constructor-arg value="200000" index="2"/>
</bean>
<!-- 按照類型匹配入參 -->
<bean id="car2" class="com.luoxn28.Car">
    <constructor-arg value="比亞迪" type="java.lang.String">
    <constructor-arg value="中國製造" type="java.lang.String"/>
    <constructor-arg value="200000" type="double"/>
</bean>

組成應用程序的 Bean 常常須要相互協做以完成應用程序的功能。要使 Bean 可以相互訪問,就必須在 Bean 配置文件中指定對 Bean 的引用,在 Bean 的配置文件中,能夠經過 <ref> 元素或 ref 屬性爲 Bean 的屬性或構造器參數指定對 Bean 的引用。也能夠在屬性或構造器裏包含 Bean 的聲明, 這樣的 Bean 稱爲內部 Bean。

<bean id="msg" class="java.lang.String">
    <constructor-arg value="luoxn28"/>
</bean>

<!-- Hello類中有一個String類型的msg屬性 -->
<bean id="hello" class="com.luoxn28.Hello">
    <property name="msg" ref="msg"/>
</bean>

當 Bean 實例僅僅給一個特定的屬性使用時,能夠將其聲明爲內部 Bean,內部 Bean 聲明直接包含在 <property> 或 <constructor-arg> 元素裏,不須要設置任何 id 或 name 屬性。內部 Bean 不能使用在任何其餘地方。

<!-- Hello類中有一個String類型的msg屬性 -->
<bean id="hello" class="com.luoxn28.Hello">
    <property name="msg">
        <bean class="java.lang.String">
            <constructor-arg value="luoxn28"/>
        </bean>
    </property>
</bean>

能夠經過一組內置的 xml 標籤(例如: <list>, <set> 或 <map>) 來配置集合屬性。

<!-- CollectionClass類有3個屬性,List<String> list、Set<String> set、Map<String, String> map-->
<bean id="collectionClass" class="com.luoxn28.CollectionClass">
    <property name="list">
        <list>
            <value>luoxn28</value>
            <value>luoxn29</value>
            <value>luoxn30</value>
        </list>
    </property>
    <property name="set">
        <set>
            <value>luoxn28</value>
            <value>luoxn29</value>
            <value>luoxn30</value>
        </set>
    </property>
    <property name="map">
        <map>
            <entry key="str1" value="luoxn28"/>
            <entry key="str2"><value>luoxn29</value></entry>
            <entry key="str3"><value>luoxn30</value></entry>
        </map>
    </property>
</bean>

 

Bean的做用域

Spring最初提供兩種bean的scope類型:singleton和prototype,在發佈2.0以後,新增了request、session和global session類型,不過這3種新增的只能用在Web應用中。能夠經過bean屬性scope來指定bean的scope類型,若是是singleton類型的話,在用戶獲取該bean以後,容器仍是會接管該bean的生命週期;若是是prototype的話,在用戶獲取該bean以後,容器就不接管該bean了,也就是容器每次會建立一個新的bean對象返回給用戶。

<!-- Hello對象每次獲取都會新建 -->
<bean id="hello" class="com.luoxn28.Hello" scope="prototype">
    <property name="msg" value="luoxn28"/>
</bean>

 

經過靜態方法建立bean

調用靜態工廠方法建立 Bean是將對象建立的過程封裝到靜態方法中,當用戶須要對象時,只須要簡單地調用靜態方法,而不一樣關心建立對象的細節。要聲明經過靜態方法建立的 Bean, 須要在 Bean 的 class 屬性裏指定擁有該工廠的方法的類, 同時在 factory-method 屬性裏指定工廠方法的名稱. 最後, 使用 <constrctor-arg> 元素爲該方法傳遞方法參數。

public static Hello createHello() {
    return new Hello();
}
<bean id="hello" class="com.luoxn28.Hello" factory-method="createHello">
</bean>

 

經過實例方法建立bean

將對象的建立過程封裝到另一個對象實例的方法裏. 當用戶須要請求對象時, 只須要簡單的調用該實例方法而不須要關心對象的建立細節。要聲明經過實例工廠方法建立的 Bean,在 bean 的 factory-bean 屬性裏指定擁有該工廠方法的 Bean,在 factory-method 屬性裏指定該工廠方法的名稱,使用 construtor-arg 元素爲工廠方法傳遞方法參數。

相關文章
相關標籤/搜索