<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Sealyu

    --- 博客已遷移至: http://www.sealyu.com/blog

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      618 隨筆 :: 87 文章 :: 225 評論 :: 0 Trackbacks
    基于注釋(Annotation)的配置有越來越流行的趨勢,Spring 2.5 順應(yīng)這種趨勢,提供了完全基于注釋配置 Bean、裝配 Bean 的功能,您可以
    使用基于注釋的 Spring IoC 替換原來基于 XML 的配置。本文通過實例詳細(xì)講述了 Spring 2.5 基于注釋 IoC 功能的使用。
    概述
    注釋配置相對于 XML 配置具有很多的優(yōu)勢:

    它可以充分利用 Java 的反射機(jī)制獲取類結(jié)構(gòu)信息,這些信息可以有效減少配置的工作。如使用 JPA 注釋配置 ORM 映射時,我們就不需要指定
    PO 的屬性名、類型等信息,如果關(guān)系表字段和 PO 屬性名、類型都一致,您甚至無需編寫任務(wù)屬性映射信息——因為這些信息都可以通過 Java
    反射機(jī)制獲取。
    注釋和 Java 代碼位于一個文件中,而 XML 配置采用獨(dú)立的配置文件,大多數(shù)配置信息在程序開發(fā)完成后都不會調(diào)整,如果配置信息和 Java 代碼
    放在一起,有助于增強(qiáng)程序的內(nèi)聚性。而采用獨(dú)立的 XML 配置文件,程序員在編寫一個功能時,往往需要在程序文件和配置文件中不停切換,這種思維
    上的不連貫會降低開發(fā)效率。
    因此在很多情況下,注釋配置比 XML 配置更受歡迎,注釋配置有進(jìn)一步流行的趨勢。Spring 2.5 的一大增強(qiáng)就是引入了很多注釋類,現(xiàn)在您已經(jīng)可以
    使用注釋配置完成大部分 XML 配置的功能。在這篇文章里,我們將向您講述使用注釋進(jìn)行 Bean 定義和依賴注入的內(nèi)容。
    原來我們是怎么做的

    在使用注釋配置之前,先來回顧一下傳統(tǒng)上是如何配置 Bean 并完成 Bean 之間依賴關(guān)系的建立。下面是 3 個類,它們分別是 Office、Car 和
    Boss,這 3 個類需要在 Spring 容器中配置為 Bean:

    Office 僅有一個屬性:


    清單 1. Office.java
                   
    package com.baobaotao;
    public class Office {
        private String officeNo =”001”;

        //省略 get/setter

        @Override
        public String toString() {
            return "officeNo:" + officeNo;
        }
    }


    Car 擁有兩個屬性:


    清單 2. Car.java
                   
    package com.baobaotao;

    public class Car {
        private String brand;
        private double price;

        // 省略 get/setter

        @Override
        public String toString() {
            return "brand:" + brand + "," + "price:" + price;
        }
    }

    Boss 擁有 Office 和 Car 類型的兩個屬性:


    清單 3. Boss.java
                   
    package com.baobaotao;

    public class Boss {
        private Car car;
        private Office office;

        // 省略 get/setter

        @Override
        public String toString() {
            return "car:" + car + ""n" + "office:" + office;
        }
    }



    我們在 Spring 容器中將 Office 和 Car 聲明為 Bean,并注入到 Boss Bean 中:下面是使用傳統(tǒng) XML 完成這個工作的配置文件 beans.xml:

    清單 4. beans.xml 將以上三個類配置成 Bean
                   
    <?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="boss" class="com.baobaotao.Boss">
            <property name="car" ref="car"/>
            <property name="office" ref="office" />
        </bean>
        <bean id="office" class="com.baobaotao.Office">
            <property name="officeNo" value="002"/>
        </bean>
        <bean id="car" class="com.baobaotao.Car" scope="singleton">
            <property name="brand" value=" 紅旗 CA72"/>
            <property name="price" value="2000"/>
        </bean>
    </beans>


    當(dāng)我們運(yùn)行以下代碼時,控制臺將正確打出 boss 的信息:


    清單 5. 測試類:AnnoIoCTest.java
                   
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    public class AnnoIoCTest {

        public static void main(String[] args) {
            String[] locations = {"beans.xml"};
            ApplicationContext ctx =
        new ClassPathXmlApplicationContext(locations);
            Boss boss = (Boss) ctx.getBean("boss");
            System.out.println(boss);
        }
    }



    這說明 Spring 容器已經(jīng)正確完成了 Bean 創(chuàng)建和裝配的工作。

    使用 @Autowired 注釋

    Spring 2.5 引入了 @Autowired 注釋,它可以對類成員變量、方法及構(gòu)造函數(shù)進(jìn)行標(biāo)注,完成自動裝配的工作。來看一下使用 @Autowired 進(jìn)行
    成員變量自動注入的代碼:


    清單 6. 使用 @Autowired 注釋的 Boss.java
                   
    package com.baobaotao;
    import org.springframework.beans.factory.annotation.Autowired;

    public class Boss {

        @Autowired
        private Car car;

        @Autowired
        private Office office;

        …
    }


    Spring 通過一個 BeanPostProcessor 對 @Autowired 進(jìn)行解析,所以要讓 @Autowired 起作用必須事先在 Spring 容器中聲明
    AutowiredAnnotationBeanPostProcessor Bean。


    清單 7. 讓 @Autowired 注釋工作起來
                   
    <?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">

        <!-- 該 BeanPostProcessor 將自動起作用,對標(biāo)注 @Autowired 的 Bean 進(jìn)行自動注入 -->
        <bean class="org.springframework.beans.factory.annotation.
            AutowiredAnnotationBeanPostProcessor"/>

        <!-- 移除 boss Bean 的屬性注入配置的信息 -->
        <bean id="boss" class="com.baobaotao.Boss"/>

        <bean id="office" class="com.baobaotao.Office">
            <property name="officeNo" value="001"/>
        </bean>
        <bean id="car" class="com.baobaotao.Car" scope="singleton">
            <property name="brand" value=" 紅旗 CA72"/>
            <property name="price" value="2000"/>
        </bean>
    </beans>


    這樣,當(dāng) Spring 容器啟動時,AutowiredAnnotationBeanPostProcessor 將掃描 Spring 容器中所有 Bean,當(dāng)發(fā)現(xiàn) Bean 中擁有
    @Autowired 注釋時就找到和其匹配(默認(rèn)按類型匹配)的 Bean,并注入到對應(yīng)的地方中去。

    按照上面的配置,Spring 將直接采用 Java 反射機(jī)制對 Boss 中的 car 和 office 這兩個私有成員變量進(jìn)行自動注入。所以對成員變量使用
    @Autowired 后,您大可將它們的 setter 方法(setCar() 和 setOffice())從 Boss 中刪除。

    當(dāng)然,您也可以通過 @Autowired 對方法或構(gòu)造函數(shù)進(jìn)行標(biāo)注,來看下面的代碼:


    清單 8. 將 @Autowired 注釋標(biāo)注在 Setter 方法上
                   
    package com.baobaotao;

    public class Boss {
        private Car car;
        private Office office;

         @Autowired
        public void setCar(Car car) {
            this.car = car;
        }

        @Autowired
        public void setOffice(Office office) {
            this.office = office;
        }
        …
    }


    這時,@Autowired 將查找被標(biāo)注的方法的入?yún)㈩愋偷?Bean,并調(diào)用方法自動注入這些 Bean。而下面的使用方法則對構(gòu)造函數(shù)進(jìn)行標(biāo)注:


    清單 9. 將 @Autowired 注釋標(biāo)注在構(gòu)造函數(shù)上
                   
    package com.baobaotao;

    public class Boss {
        private Car car;
        private Office office;

        @Autowired
        public Boss(Car car ,Office office){
            this.car = car;
            this.office = office ;
        }

        …
    }

    由于 Boss() 構(gòu)造函數(shù)有兩個入?yún)ⅲ謩e是 car 和 office,@Autowired 將分別尋找和它們類型匹配的 Bean,將它們作為
    Boss(Car car ,Office office) 的入?yún)韯?chuàng)建 Boss Bean。


    當(dāng)候選 Bean 數(shù)目不為 1 時的應(yīng)對方法

    在默認(rèn)情況下使用 @Autowired 注釋進(jìn)行自動注入時,Spring 容器中匹配的候選 Bean 數(shù)目必須有且僅有一個。當(dāng)找不到一個匹配的 Bean 時,
    Spring 容器將拋出 BeanCreationException 異常,并指出必須至少擁有一個匹配的 Bean。我們可以來做一個實驗:


    清單 10. 候選 Bean 數(shù)目為 0 時
                   
    <?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 class="org.springframework.beans.factory.annotation.
            AutowiredAnnotationBeanPostProcessor"/>

        <bean id="boss" class="com.baobaotao.Boss"/>

        <!-- 將 office Bean 注釋掉 -->
        <!-- <bean id="office" class="com.baobaotao.Office">
        <property name="officeNo" value="001"/>
        </bean>-->

        <bean id="car" class="com.baobaotao.Car" scope="singleton">
            <property name="brand" value=" 紅旗 CA72"/>
            <property name="price" value="2000"/>
        </bean>
    </beans>



    由于 office Bean 被注釋掉了,所以 Spring 容器中將沒有類型為 Office 的 Bean 了,而 Boss 的 office 屬性標(biāo)注了 @Autowired,
    當(dāng)啟動 Spring 容器時,異常就產(chǎn)生了。

    當(dāng)不能確定 Spring 容器中一定擁有某個類的 Bean 時,可以在需要自動注入該類 Bean 的地方可以使用 @Autowired(required = false),
    這等于告訴 Spring:在找不到匹配 Bean 時也不報錯。來看一下具體的例子:


    清單 11. 使用 @Autowired(required = false)
                   
    package com.baobaotao;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Required;

    public class Boss {

        private Car car;
        private Office office;

        @Autowired
        public void setCar(Car car) {
            this.car = car;
        }
        @Autowired(required = false)
        public void setOffice(Office office) {
            this.office = office;
        }
        …
    }



    當(dāng)然,一般情況下,使用 @Autowired 的地方都是需要注入 Bean 的,使用了自動注入而又允許不注入的情況一般僅會在開發(fā)期或測試期碰到
    (如為了快速啟動 Spring 容器,僅引入一些模塊的 Spring 配置文件),所以 @Autowired(required = false) 會很少用到。

    和找不到一個類型匹配 Bean 相反的一個錯誤是:如果 Spring 容器中擁有多個候選 Bean,Spring 容器在啟動時也會拋出
    BeanCreationException 異常。來看下面的例子:


    清單 12. 在 beans.xml 中配置兩個 Office 類型的 Bean
                   

    <bean id="office" class="com.baobaotao.Office">
        <property name="officeNo" value="001"/>
    </bean>
    <bean id="office2" class="com.baobaotao.Office">
        <property name="officeNo" value="001"/>
    </bean>




    我們在 Spring 容器中配置了兩個類型為 Office 類型的 Bean,當(dāng)對 Boss 的 office 成員變量進(jìn)行自動注入時,Spring 容器將無法確定到
    底要用哪一個 Bean,因此異常發(fā)生了。

    Spring 允許我們通過 @Qualifier 注釋指定注入 Bean 的名稱,這樣歧義就消除了,可以通過下面的方法解決異常:


    清單 13. 使用 @Qualifier 注釋指定注入 Bean 的名稱
                   
    @Autowired
    public void setOffice(@Qualifier("office")Office office) {
        this.office = office;
    }



    @Qualifier("office") 中的 office 是 Bean 的名稱,所以 @Autowired 和 @Qualifier 結(jié)合使用時,自動注入的策略就從 byType
    轉(zhuǎn)變成 byName 了。@Autowired 可以對成員變量、方法以及構(gòu)造函數(shù)進(jìn)行注釋,而 @Qualifier 的標(biāo)注對象是成員變量、方法入?yún)ⅰ?gòu)造函數(shù)入
    參。正是由于注釋對象的不同,所以 Spring 不將 @Autowired 和 @Qualifier 統(tǒng)一成一個注釋類。下面是對成員變量和構(gòu)造函數(shù)入?yún)⑦M(jìn)行注釋的
    代碼:

    對成員變量進(jìn)行注釋:


    清單 14. 對成員變量使用 @Qualifier 注釋
                   
    public class Boss {
        @Autowired
        private Car car;

        @Autowired
        @Qualifier("office")
        private Office office;
        …
    }



    對構(gòu)造函數(shù)入?yún)⑦M(jìn)行注釋:

    清單 15. 對構(gòu)造函數(shù)變量使用 @Qualifier 注釋
                   
    public class Boss {
        private Car car;
        private Office office;

        @Autowired
        public Boss(Car car , @Qualifier("office")Office office){
            this.car = car;
            this.office = office ;
    }
    }


    @Qualifier 只能和 @Autowired 結(jié)合使用,是對 @Autowired 有益的補(bǔ)充。一般來講,@Qualifier 對方法簽名中入?yún)⑦M(jìn)行注釋會降低代碼的
    可讀性,而對成員變量注釋則相對好一些。

    使用 JSR-250 的注釋

    Spring 不但支持自己定義的 @Autowired 的注釋,還支持幾個由 JSR-250 規(guī)范定義的注釋,它們分別是 @Resource、@PostConstruct 以及
    @PreDestroy。

    @Resource

    @Resource 的作用相當(dāng)于 @Autowired,只不過 @Autowired 按 byType 自動注入,面 @Resource 默認(rèn)按 byName 自動注入罷了。
    @Resource 有兩個屬性是比較重要的,分別是 name 和 type,Spring 將 @Resource 注釋的 name 屬性解析為 Bean 的名字,而 type
    屬性則解析為 Bean 的類型。所以如果使用 name 屬性,則使用 byName 的自動注入策略,而使用 type 屬性時則使用 byType 自動注入策略。
    如果既不指定 name 也不指定 type 屬性,這時將通過反射機(jī)制使用 byName 自動注入策略。

    Resource 注釋類位于 Spring 發(fā)布包的 lib/j2ee/common-annotations.jar 類包中,因此在使用之前必須將其加入到項目的類庫中。
    來看一個使用 @Resource 的例子:


    清單 16. 使用 @Resource 注釋的 Boss.java
                   
    package com.baobaotao;

    import javax.annotation.Resource;

    public class Boss {
        // 自動注入類型為 Car 的 Bean
        @Resource
        private Car car;

        // 自動注入 bean 名稱為 office 的 Bean
        @Resource(name = "office")
        private Office office;
    }



    一般情況下,我們無需使用類似于 @Resource(type=Car.class) 的注釋方式,因為 Bean 的類型信息可以通過 Java 反射從代碼中獲取。

    要讓 JSR-250 的注釋生效,除了在 Bean 類中標(biāo)注這些注釋外,還需要在 Spring 容器中注冊一個負(fù)責(zé)處理這些注釋的 BeanPostProcessor:

    <bean
      class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>



    CommonAnnotationBeanPostProcessor 實現(xiàn)了 BeanPostProcessor 接口,它負(fù)責(zé)掃描使用了 JSR-250 注釋的 Bean,并對它們進(jìn)行相應(yīng)的操作。

    @PostConstruct 和 @PreDestroy

    Spring 容器中的 Bean 是有生命周期的,Spring 允許在 Bean 在初始化完成后以及 Bean 銷毀前執(zhí)行特定的操作,您既可以通過實現(xiàn) InitializingBean/DisposableBean 接口來定制初始化之后 / 銷毀之前的操作方法,也可以通過 <bean> 元素的 init-method/destroy-method 屬性指定初始化之后 / 銷毀之前調(diào)用的操作方法。關(guān)于 Spring 的生命周期,筆者在《精通 Spring 2.x—企業(yè)應(yīng)用開發(fā)精解》第 3 章進(jìn)行了詳細(xì)的描述,有興趣的讀者可以查閱。

    JSR-250 為初始化之后/銷毀之前方法的指定定義了兩個注釋類,分別是 @PostConstruct 和 @PreDestroy,這兩個注釋只能應(yīng)用于方法上。標(biāo)注了 @PostConstruct 注釋的方法將在類實例化后調(diào)用,而標(biāo)注了 @PreDestroy 的方法將在類銷毀之前調(diào)用。


    清單 17. 使用 @PostConstruct 和 @PreDestroy 注釋的 Boss.java
                   
    package com.baobaotao;

    import javax.annotation.Resource;
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;

    public class Boss {
        @Resource
        private Car car;

        @Resource(name = "office")
        private Office office;

        @PostConstruct
        public void postConstruct1(){
            System.out.println("postConstruct1");
        }

        @PreDestroy
        public void preDestroy1(){
            System.out.println("preDestroy1");
        }
        …
    }


    您只需要在方法前標(biāo)注 @PostConstruct 或 @PreDestroy,這些方法就會在 Bean 初始化后或銷毀之前被 Spring 容器執(zhí)行了。

    我們知道,不管是通過實現(xiàn) InitializingBean/DisposableBean 接口,還是通過 <bean> 元素的 init-method/destroy-method 屬性進(jìn)行配置,都只能為 Bean 指定一個初始化 / 銷毀的方法。但是使用 @PostConstruct 和 @PreDestroy 注釋卻可以指定多個初始化 / 銷毀方法,那些被標(biāo)注 @PostConstruct 或 @PreDestroy 注釋的方法都會在初始化 / 銷毀時被執(zhí)行。

    通過以下的測試代碼,您將可以看到 Bean 的初始化 / 銷毀方法是如何被執(zhí)行的:


    清單 18. 測試類代碼
                   
    package com.baobaotao;

    import org.springframework.context.support.ClassPathXmlApplicationContext;

    public class AnnoIoCTest {

        public static void main(String[] args) {
            String[] locations = {"beans.xml"};
            ClassPathXmlApplicationContext ctx =
                new ClassPathXmlApplicationContext(locations);
            Boss boss = (Boss) ctx.getBean("boss");
            System.out.println(boss);
            ctx.destroy();// 關(guān)閉 Spring 容器,以觸發(fā) Bean 銷毀方法的執(zhí)行
        }
    }



    這時,您將看到標(biāo)注了 @PostConstruct 的 postConstruct1() 方法將在 Spring 容器啟動時,創(chuàng)建 Boss Bean 的時候被觸發(fā)執(zhí)行,而標(biāo)注了 @PreDestroy 注釋的 preDestroy1() 方法將在 Spring 容器關(guān)閉前銷毀 Boss Bean 的時候被觸發(fā)執(zhí)行。

    使用 <context:annotation-config/> 簡化配置

    Spring 2.1 添加了一個新的 context 的 Schema 命名空間,該命名空間對注釋驅(qū)動、屬性文件引入、加載期織入等功能提供了便捷的配置。我們知道注釋本身是不會做任何事情的,它僅提供元數(shù)據(jù)信息。要使元數(shù) 據(jù)信息真正起作用,必須讓負(fù)責(zé)處理這些元數(shù)據(jù)的處理器工作起來。

    而我們前面所介紹的 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor 就是處理這些注釋元數(shù)據(jù)的處理器。但是直接在 Spring 配置文件中定義這些 Bean 顯得比較笨拙。Spring 為我們提供了一種方便的注冊這些 BeanPostProcessor 的方式,這就是 <context:annotation-config/>。請看下面的配置:


    清單 19. 調(diào)整 beans.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"
         xmlns:context="http://www.springframework.org/schema/context"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">

        <context:annotation-config/>

        <bean id="boss" class="com.baobaotao.Boss"/>
        <bean id="office" class="com.baobaotao.Office">
            <property name="officeNo" value="001"/>
        </bean>
        <bean id="car" class="com.baobaotao.Car" scope="singleton">
            <property name="brand" value=" 紅旗 CA72"/>
            <property name="price" value="2000"/>
        </bean>
    </beans>



    <context:annotationconfig/> 將隱式地向 Spring 容器注冊 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、 PersistenceAnnotationBeanPostProcessor 以及 equiredAnnotationBeanPostProcessor 這 4 個 BeanPostProcessor。

    在配置文件中使用 context 命名空間之前,必須在 <beans> 元素中聲明 context 命名空間。

    使用 @Component

    雖然我們可以通過 @Autowired 或 @Resource 在 Bean 類中使用自動注入功能,但是 Bean 還是在 XML 文件中通過 <bean> 進(jìn)行定義 ——
    也就是說,在 XML 配置文件中定義 Bean,通過 @Autowired 或 @Resource 為 Bean 的成員變量、方法入?yún)⒒驑?gòu)造函數(shù)入?yún)⑻峁┳詣幼⑷氲墓δ?
    。能否也通過注釋定義 Bean,從 XML 配置文件中完全移除 Bean 定義的配置呢?答案是肯定的,我們通過 Spring 2.5 提供的 @Component
    注釋就可以達(dá)到這個目標(biāo)了。

    下面,我們完全使用注釋定義 Bean 并完成 Bean 之間裝配:


    清單 20. 使用 @Component 注釋的 Car.java
                   
    package com.baobaotao;

    import org.springframework.stereotype.Component;

    @Component
    public class Car {
        …
    }



    僅需要在類定義處,使用 @Component 注釋就可以將一個類定義了 Spring 容器中的 Bean。下面的代碼將 Office 定義為一個 Bean:


    清單 21. 使用 @Component 注釋的 Office.java
                   
    package com.baobaotao;

    import org.springframework.stereotype.Component;

    @Component
    public class Office {
        private String officeNo = "001";
        …
    }



    這樣,我們就可以在 Boss 類中通過 @Autowired 注入前面定義的 Car 和 Office Bean 了。


    清單 22. 使用 @Component 注釋的 Boss.java
                   
    package com.baobaotao;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Required;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.stereotype.Component;

    @Component("boss")
    public class Boss {
        @Autowired
        private Car car;

        @Autowired
        private Office office;
        …
    }



    @Component 有一個可選的入?yún)ⅲ糜谥付?Bean 的名稱,在 Boss 中,我們就將 Bean 名稱定義為“boss”。一般情況下,
    Bean 都是 singleton 的,需要注入 Bean 的地方僅需要通過 byType 策略就可以自動注入了,所以大可不必指定 Bean 的名稱。


    在使用 @Component 注釋后,Spring 容器必須啟用類掃描機(jī)制以啟用注釋驅(qū)動 Bean 定義和注釋驅(qū)動 Bean 自動注入的策略。
    Spring 2.5 對 context 命名空間進(jìn)行了擴(kuò)展,提供了這一功能,請看下面的配置:

    清單 23. 簡化版的 beans.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"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">
        <context:component-scan base-package="com.baobaotao"/>
    </beans>


    這里,所有通過 <bean> 元素定義 Bean 的配置內(nèi)容已經(jīng)被移除,僅需要添加一行 <context:component-scan/> 配置就解決所有問題了
    ——Spring XML 配置文件得到了極致的簡化(當(dāng)然配置元數(shù)據(jù)還是需要的,只不過以注釋形式存在罷了)。<context:component-scan/>
    的 base-package 屬性指定了需要掃描的類包,類包及其遞歸子包中所有的類都會被處理。

    <context:component-scan/> 還允許定義過濾器將基包下的某些類納入或排除。Spring 支持以下 4 種類型的過濾方式,通過下表說明:

    表 1. 掃描過濾方式
    過濾器類型 說明
    注釋 假如 com.baobaotao.SomeAnnotation 是一個注釋類,我們可以將使用該注釋的類過濾出來。
    類名指定 通過全限定類名進(jìn)行過濾,如您可以指定將 com.baobaotao.Boss 納入掃描,而將 com.baobaotao.Car 排除在外。
    正則表達(dá)式 通過正則表達(dá)式定義過濾的類,如下所示: com".baobaotao".Default.*
    AspectJ 表達(dá)式 通過 AspectJ 表達(dá)式定義過濾的類,如下所示: com. baobaotao..*Service+

    下面是一個簡單的例子:

    <context:component-scan base-package="com.baobaotao">
        <context:include-filter type="regex"
            expression="com".baobaotao".service"..*"/>
        <context:exclude-filter type="aspectj"
            expression="com.baobaotao.util..*"/>
    </context:component-scan>


    值得注意的是 <context:component-scan/> 配置項不但啟用了對類包進(jìn)行掃描以實施注釋驅(qū)動 Bean 定義的功能,同時還啟用了注釋驅(qū)動自動注入
    的功能(即還隱式地在內(nèi)部注冊了 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor),因此當(dāng)使用
    <context:component-scan/> 后,就可以將 <context:annotation-config/> 移除了。

    默認(rèn)情況下通過 @Component 定義的 Bean 都是 singleton 的,如果需要使用其它作用范圍的 Bean,可以通過 @Scope 注釋來達(dá)到目標(biāo),如以
    下代碼所示:


    清單 24. 通過 @Scope 指定 Bean 的作用范圍
                   
    package com.baobaotao;
    import org.springframework.context.annotation.Scope;

    @Scope("prototype")
    @Component("boss")
    public class Boss {
        …
    }



    這樣,當(dāng)從 Spring 容器中獲取 boss Bean 時,每次返回的都是新的實例了。


    采用具有特殊語義的注釋

    Spring 2.5 中除了提供 @Component 注釋外,還定義了幾個擁有特殊語義的注釋,它們分別是:@Repository、@Service
    和 @Controller。在目前的 Spring 版本中,這 3 個注釋和 @Component 是等效的,但是從注釋類的命名上,很容易看出這
    3 個注釋分別和持久層、業(yè)務(wù)層和控制層(Web 層)相對應(yīng)。雖然目前這 3 個注釋和 @Component 相比沒有什么新意,
    但 Spring 將在以后的版本中為它們添加特殊的功能。所以,如果 Web 應(yīng)用程序采用了經(jīng)典的三層分層結(jié)構(gòu)的話,最好在持久層、業(yè)務(wù)層和控制層
    分別采用 @Repository、@Service 和 @Controller 對分層中的類進(jìn)行注釋,而用 @Component 對那些比較中立的類進(jìn)行注釋。

    如果 Bean 不是自己編寫的類(如 JdbcTemplate、SessionFactoryBean 等),注釋配置將無法實施,此時 XML 配置是唯一可用的方式。
    注釋配置往往是類級別的,而 XML 配置則可以表現(xiàn)得更加靈活。比如相比于 @Transaction 事務(wù)注釋,使用 aop/tx 命名空間的事務(wù)配置更加靈活
    和簡單。
    所以在實現(xiàn)應(yīng)用中,我們往往需要同時使用注釋配置和 XML 配置,對于類級別且不會發(fā)生變動的配置可以優(yōu)先考慮注釋配置;而對于那些第三方類以及
    容易發(fā)生調(diào)整的配置則應(yīng)優(yōu)先考慮使用 XML 配置。Spring 會在具體實施 Bean 創(chuàng)建和 Bean 注入之前將這兩種配置方式的元信息融合在一起。

    小結(jié)

    Spring 在 2.1 以后對注釋配置提供了強(qiáng)力的支持,注釋配置功能成為 Spring 2.5 的最大的亮點(diǎn)之一。合理地使用 Spring 2.5 的注釋配置,
    可以有效減少配置的工作量,提高程序的內(nèi)聚性。但是這并不意味著傳統(tǒng) XML 配置將走向消亡,在第三方類 Bean 的配置,以及那些諸如數(shù)據(jù)源、
    緩存池、持久層操作模板類、事務(wù)管理等內(nèi)容的配置上,XML 配置依然擁有不可替代的地位。
    spring 事務(wù)管理(Transaction) 例子
     
     
    ##Transaction) 例子  
    傳統(tǒng)上, J2EE開發(fā)者有兩種事務(wù)管理選擇,全局和本地事務(wù)。Spring框架對事務(wù)管理的支持極大地改變傳統(tǒng)上認(rèn)為J2EE應(yīng)用需要應(yīng)用服務(wù)器。這種
    改變不單是僅僅為了通過EJB來使用生命式事務(wù)而使用應(yīng)用服務(wù)器。事實上,即使你的應(yīng)用服務(wù)器有強(qiáng)大的JTA功能,Spring框架的聲明式事務(wù)提供了
    比EJB CMT(聲明式事務(wù))更強(qiáng)大,更高效的編程模型。一般來說,只有支持多個事務(wù)資源,才會需要應(yīng)用服務(wù)器的JTA功能,而大多數(shù)應(yīng)用不需要能夠
    處理跨多種資源。最重要的一點(diǎn),使用Spring,你可以選擇何時把你的應(yīng)用遷移到全功能的應(yīng)用服務(wù)器。使用Spring不需要像以前一樣用編碼實現(xiàn)本地
    事務(wù)代替EJB CMT或JTA,現(xiàn)在只需要改配置問價,而不必改代碼。
    一. Spring事務(wù)管理

      1. Spring 編程式事務(wù)管理(programmatic transaction management)
       DefaultTransactionDefinition def = new DefaultTransactionDefinition();
    TransactionStatus status = transactionManager.getTransaction(def);
    try {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

    jdbcTemplate.update("INSERT INTO USER VALUES('Spring008', 'caterpillar', 'M', 29)");

    jdbcTemplate.update("INSERT INTO USER VALUES('Spring009', 'momor', 'F', 26)");
    jdbcTemplate.update("INSERT INTO USER VALUES('Spring010, 'beckyday', 'F', 35)");

    } catch (DataAccessException ex) {

    transactionManager.rollback(status); // 也可以執(zhí)行status.setRollbackOnly();
            throw ex;
    }
    transactionManager.commit(status);

    見:http://www.javaworld.com.tw/confluence/pages/viewpage.action?pageId=2398

      2. Spring宣告式事務(wù)管理(declarative transaction management)主要是在spring的配置文件中設(shè)置

        

        <bean id="userDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">



    <property name="transactionManager">



    <ref bean="transactionManager"/>



    </property>



    <property name="target">



    <ref bean="userDAO"/>



    </property>



    <property name="transactionAttributes">



    <props>



    <prop key="insert*">PROPAGATION_REQUIRED</prop>



    </props>



    </property>       



    </bean>

    見:http://www.javaworld.com.tw/confluence/pages/viewpage.action?pageId=2402
    二. Spring的@Transcation的例子

    1. class 中

    @Component //注釋就可以將該類定義了 Spring 容器中的 Bean

    public Class UserDaoImpl implements IUserDao {
    @Override
    //標(biāo)志updateUsers()為Transactional    
    @Transactional(
    propagation = Propagation.REQUIRED,
    isolation = Isolation.DEFAULT,
    rollbackFor = Exception.class
    )
    public void updateUsers(List<User> users){
    for(User user :users){
    //邏輯
    }
    }
    }
    注意: 事務(wù)的屬性和基本概念



    Required : 如果在一個事務(wù)中調(diào)用,就將該方法加到此事務(wù)中,如果沒有啟動事務(wù),就創(chuàng)建新事務(wù)



    RequiredNew : 不管當(dāng)前有沒有事務(wù),都啟動新事務(wù),如果有,會被掛起,直到此方法結(jié)束



    NotSupported : 不能在事務(wù)中執(zhí)行此方法,如果有事務(wù),會被掛起,直到此方法結(jié)束 



    Supports : 如果有當(dāng)前事務(wù),此方法回加到當(dāng)前事務(wù),如果沒有,容器不會啟動新事務(wù)



    Mandatory : 必須在事務(wù)中執(zhí)行此方法,否則會拋出異常 : TransactionRequiredException



    Never : 必須不在事務(wù)中調(diào)用此方法,否則拋出RemoteException(遠(yuǎn)程調(diào)用)或EJBException(本地調(diào)用)
            2.spring配置文件加入:
               .....................
                <tx:annotation-driven/>
              .....................

          注意: webSerivces 是不支持事務(wù)的,如果使用事務(wù),必須在下層的Object中實現(xiàn),例如在Service層或者是Dao層實現(xiàn)。

    1. 使用Spring注解來注入屬性
    1.1. 使用注解以前我們是怎樣注入屬性的
    類的實現(xiàn):
    Java代碼
    public class UserManagerImpl implements UserManager {  
        private UserDao userDao;  
        public void setUserDao(UserDao userDao) {  
            this.userDao = userDao;  
        }  
        ...  


    public class UserManagerImpl implements UserManager {
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
    }
    ...
    }

    配置文件:
    Java代碼
    <bean id="userManagerImpl" class="com.kedacom.spring.annotation.service.UserManagerImpl">  
        <property name="userDao" ref="userDao" />  
    </bean>  
    <bean id="userDao" class="com.kedacom.spring.annotation.persistence.UserDaoImpl">  
        <property name="sessionFactory" ref="mySessionFactory" />  
    </bean> 

    <bean id="userManagerImpl" class="com.kedacom.spring.annotation.service.UserManagerImpl">
    <property name="userDao" ref="userDao" />
    </bean>
    <bean id="userDao" class="com.kedacom.spring.annotation.persistence.UserDaoImpl">
    <property name="sessionFactory" ref="mySessionFactory" />
    </bean>


    1.2. 引入@Autowired注解(不推薦使用,建議使用@Resource)
    類的實現(xiàn)(對成員變量進(jìn)行標(biāo)注)
    Java代碼
    public class UserManagerImpl implements UserManager {  
        @Autowired 
        private UserDao userDao;  
        ...  


    public class UserManagerImpl implements UserManager {
    @Autowired
    private UserDao userDao;
    ...
    }

    或者(對方法進(jìn)行標(biāo)注)
    Java代碼
    public class UserManagerImpl implements UserManager {  
        private UserDao userDao;  
        @Autowired 
        public void setUserDao(UserDao userDao) {  
            this.userDao = userDao;  
        }  
        ...  


    public class UserManagerImpl implements UserManager {
    private UserDao userDao;
    @Autowired
    public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
    }
    ...
    }
    配置文件
    Java代碼
    <bean id="userManagerImpl" class="com.kedacom.spring.annotation.service.UserManagerImpl" />  
    <bean id="userDao" class="com.kedacom.spring.annotation.persistence.UserDaoImpl">  
        <property name="sessionFactory" ref="mySessionFactory" />  
    </bean> 

    <bean id="userManagerImpl" class="com.kedacom.spring.annotation.service.UserManagerImpl" />
    <bean id="userDao" class="com.kedacom.spring.annotation.persistence.UserDaoImpl">
    <property name="sessionFactory" ref="mySessionFactory" />
    </bean>

    @Autowired可以對成員變量、方法和構(gòu)造函數(shù)進(jìn)行標(biāo)注,來完成自動裝配的工作。以上兩種不同實現(xiàn)方式中,@Autowired的標(biāo)注位置不同,它們都會在Spring在初始化userManagerImpl這個bean時,自動裝配userDao這個屬性,區(qū)別是:第一種實現(xiàn)中,Spring會直接將UserDao類型的唯一一個bean賦值給userDao這個成員變量;第二種實現(xiàn)中,Spring會調(diào)用setUserDao方法來將UserDao類型的唯一一個bean裝配到userDao這個屬性。

    1.3. 讓@Autowired工作起來
    要使@Autowired能夠工作,還需要在配置文件中加入以下代碼
    Java代碼
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" /> 

    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />


    1.4. @Qualifier
    @Autowired是根據(jù)類型進(jìn)行自動裝配的。在上面的例子中,如果當(dāng)Spring上下文中存在不止一個UserDao類型的bean時,就會拋出BeanCreationException異常;如果Spring上下文中不存在UserDao類型的bean,也會拋出BeanCreationException異常。我們可以使用@Qualifier配合@Autowired來解決這些問題。
    1. 可能存在多個UserDao實例
    Java代碼
    @Autowired 
    public void setUserDao(@Qualifier("userDao") UserDao userDao) {  
        this.userDao = userDao;  


    @Autowired
    public void setUserDao(@Qualifier("userDao") UserDao userDao) {
    this.userDao = userDao;
    }

    這樣,Spring會找到id為userDao的bean進(jìn)行裝配。
    2. 可能不存在UserDao實例

    Java代碼
    @Autowired(required = false)  
    public void setUserDao(UserDao userDao) {  
        this.userDao = userDao;  


    @Autowired(required = false)
    public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
    }


    1.5. @Resource(JSR-250標(biāo)準(zhǔn)注解,推薦使用它來代替Spring專有的@Autowired注解)
    Spring 不但支持自己定義的@Autowired注解,還支持幾個由JSR-250規(guī)范定義的注解,它們分別是@Resource、@PostConstruct以及@PreDestroy。
    @Resource的作用相當(dāng)于@Autowired,只不過@Autowired按byType自動注入,而@Resource默認(rèn)按byName自動注入罷了。@Resource有兩個屬性是比較重要的,分別是name和type,Spring將 @Resource注解的name屬性解析為bean的名字,而type屬性則解析為bean的類型。所以如果使用name屬性,則使用byName的自 動注入策略,而使用type屬性時則使用byType自動注入策略。如果既不指定name也不指定type屬性,這時將通過反射機(jī)制使用byName自動 注入策略。
    @Resource裝配順序

    如果同時指定了name和type,則從Spring上下文中找到唯一匹配的bean進(jìn)行裝配,找不到則拋出異常
    如果指定了name,則從上下文中查找名稱(id)匹配的bean進(jìn)行裝配,找不到則拋出異常
    如果指定了type,則從上下文中找到類型匹配的唯一bean進(jìn)行裝配,找不到或者找到多個,都會拋出異常
    如果既沒有指定name,又沒有指定type,則自動按照byName方式進(jìn)行裝配(見2);如果沒有匹配,則回退為一個原始類型(UserDao)進(jìn)行匹配,如果匹配則自動裝配;


    1.6. @PostConstruct(JSR-250)
    在方法上加上注解@PostConstruct,這個方法就會在Bean初始化之后被Spring容器執(zhí)行(注:Bean初始化包括,實例化Bean,并裝配Bean的屬性(依賴注入))。
    它的一個典型的應(yīng)用場景是,當(dāng)你需要往Bean里注入一個其父類中定義的屬性,而你又無法復(fù)寫父類的屬性或?qū)傩缘膕etter方法時,如:
    Java代碼
    public class UserDaoImpl extends HibernateDaoSupport implements UserDao {  
        private SessionFactory mySessionFacotry;  
        @Resource 
        public void setMySessionFacotry(SessionFactory sessionFacotry) {  
            this.mySessionFacotry = sessionFacotry;  
        }  
        @PostConstruct 
        public void injectSessionFactory() {  
            super.setSessionFactory(mySessionFacotry);  
        }  
        ...  


    public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
    private SessionFactory mySessionFacotry;
    @Resource
    public void setMySessionFacotry(SessionFactory sessionFacotry) {
    this.mySessionFacotry = sessionFacotry;
    }
    @PostConstruct
    public void injectSessionFactory() {
    super.setSessionFactory(mySessionFacotry);
    }
    ...
    }

    這里通過@PostConstruct,為UserDaoImpl的父類里定義的一個sessionFactory私有屬性,注入了我們自己定義 的sessionFactory(父類的setSessionFactory方法為final,不可復(fù)寫),之后我們就可以通過調(diào)用 super.getSessionFactory()來訪問該屬性了。

    1.7. @PreDestroy(JSR-250)
    在方法上加上注解@PreDestroy,這個方法就會在Bean初始化之后被Spring容器執(zhí)行。由于我們當(dāng)前還沒有需要用到它的場景,這里不不去演示。其用法同@PostConstruct。

    1.8. 使用<context:annotation-config />簡化配置
    Spring2.1添加了一個新的context的Schema命名空間,該命名空間對注釋驅(qū)動、屬性文件引入、加載期織入等功能提供了便捷的配 置。我們知道注釋本身是不會做任何事情的,它僅提供元數(shù)據(jù)信息。要使元數(shù)據(jù)信息真正起作用,必須讓負(fù)責(zé)處理這些元數(shù)據(jù)的處理器工作起來。
    AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor就是處理這些注釋元數(shù)據(jù)的處理器。但是直接在Spring配置文件中定義這些Bean顯得比較笨拙。Spring為我們提供了一種方便的注冊這些BeanPostProcessor的方式,這就是<context:annotation-config />:
    Java代碼
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 
        xsi:schemaLocation="http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
        http://www.springframework.org/schema/context  
        http://www.springframework.org/schema/context/spring-context-2.5.xsd">  
        <context:annotation-config />  
    </beans> 

    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:annotation-config />
    </beans>

    <context:annotationconfig />將隱式地向Spring容 器注冊AutowiredAnnotationBeanPostProcessor、 CommonAnnotationBeanPostProcessor、 PersistenceAnnotationBeanPostProcessor以及 RequiredAnnotationBeanPostProcessor這4個BeanPostProcessor。

    2. 使用Spring注解完成Bean的定義
    以上我們介紹了通過@Autowired或@Resource來實現(xiàn)在Bean中自動注入的功能,下面我們將介紹如何注解Bean,從而從XML配置文件中完全移除Bean定義的配置。

    2.1. @Component(不推薦使用)、@Repository、@Service、@Controller
    只需要在對應(yīng)的類上加上一個@Component注解,就將該類定義為一個Bean了:
    Java代碼
    @Component 
    public class UserDaoImpl extends HibernateDaoSupport implements UserDao {  
        ...  


    @Component
    public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
    ...
    }

    使用@Component注解定義的Bean,默認(rèn)的名稱(id)是小寫開頭的非限定類名。如這里定義的Bean名稱就是userDaoImpl。你也可以指定Bean的名稱:
    @Component("userDao")
    @Component是所有受Spring管理組件的通用形式,Spring還提供了更加細(xì)化的注解形式:@Repository、@Service、@Controller,它們分別對應(yīng)存儲層Bean,業(yè)務(wù)層Bean,和展示層Bean。目前版本(2.5)中,這些注解與@Component的語義是一樣的,完全通用,在Spring以后的版本中可能會給它們追加更多的語義。所以,我們推薦使用@Repository、@Service、@Controller來替代@Component。

    2.2. 使用<context:component-scan />讓Bean定義注解工作起來
    Java代碼
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 
        xsi:schemaLocation="http://www.springframework.org/schema/beans  
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
        http://www.springframework.org/schema/context  
        http://www.springframework.org/schema/context/spring-context-2.5.xsd">  
        <context:component-scan base-package="com.kedacom.ksoa" />  
    </beans> 

    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <context:component-scan base-package="com.kedacom.ksoa" />
    </beans>

    這里,所有通過<bean>元素定義Bean的配置內(nèi)容已經(jīng)被移除,僅需要添加一行<context:component-scan />配置就解決所有問題了——Spring XML配置文件得到了極致的簡化(當(dāng)然配置元數(shù)據(jù)還是需要的,只不過以注釋形式存在罷了)。<context:component-scan />的base-package屬性指定了需要掃描的類包,類包及其遞歸子包中所有的類都會被處理。
    <context:component-scan />還允許定義過濾器將基包下的某些類納入或排除。Spring支持以下4種類型的過濾方式:

    過濾器類型 表達(dá)式范例 說明
    注解 org.example.SomeAnnotation 將所有使用SomeAnnotation注解的類過濾出來
    類名指定 org.example.SomeClass 過濾指定的類
    正則表達(dá)式 com".kedacom".spring".annotation".web"..* 通過正則表達(dá)式過濾一些類
    AspectJ表達(dá)式 org.example..*Service+ 通過AspectJ表達(dá)式過濾一些類

    以正則表達(dá)式為例,我列舉一個應(yīng)用實例:
    Java代碼
    <context:component-scan base-package="com.casheen.spring.annotation">  
        <context:exclude-filter type="regex" expression="com".casheen".spring".annotation".web"..*" />  
    </context:component-scan> 

    <context:component-scan base-package="com.casheen.spring.annotation">
    <context:exclude-filter type="regex" expression="com".casheen".spring".annotation".web"..*" />
    </context:component-scan>

    值得注意的是<context:component-scan />配置項不但啟用了對類包進(jìn)行掃描以實施注釋驅(qū)動Bean定義的功能,同時還啟用了注釋驅(qū)動自動注入的功能(即還隱式地在內(nèi)部注冊了 AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor), 因此當(dāng)使用<context:component-scan />后,就可以將<context:annotation-config />移除了。

    2.3. 使用@Scope來定義Bean的作用范圍
    在使用XML定義Bean時,我們可能還需要通過bean的scope屬性來定義一個Bean的作用范圍,我們同樣可以通過@Scope注解來完成這項工作:
    Java代碼
    @Scope("session")  
    @Component()  
    public class UserSessionBean implements Serializable {  
        ...  


    @Scope("session")
    @Component()
    public class UserSessionBean implements Serializable {
    ...
    }


    3. 參考
    http://kingtai168.javaeye.com/blog/244002
    http://www.javaeye.com/topic/244153
    http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config
    http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-classpath-scanning
    posted on 2010-01-16 23:30 seal 閱讀(4821) 評論(0)  編輯  收藏 所屬分類: Spring
    主站蜘蛛池模板: 日本无卡码免费一区二区三区| 在线观看成人免费| 亚洲精品久久无码| 亚洲日本va午夜中文字幕一区| 亚洲一区二区三区国产精品| 91禁漫免费进入| 在线视频网址免费播放| 久久久久亚洲AV成人无码网站| 6080午夜一级毛片免费看6080夜福利| 久久久久亚洲?V成人无码| 18禁超污无遮挡无码免费网站国产| 色偷偷噜噜噜亚洲男人| 亚洲一区中文字幕在线观看| 久久久综合亚洲色一区二区三区| 久久久久久久久免费看无码| 蜜桃AV无码免费看永久| 污视频在线观看免费| 免费无码又爽又刺激网站直播| 亚洲中文字幕无码一去台湾| 亚洲精品无码专区2| 国产精品冒白浆免费视频| 国产免费爽爽视频在线观看| 亚洲成a人片在线观看精品| 亚洲福利精品一区二区三区| 国产色爽女小说免费看| 免费视频中文字幕| 成人毛片免费观看视频| 免费无码不卡视频在线观看 | 成年性羞羞视频免费观看无限| 一级毛片a免费播放王色| 亚洲最大免费视频网| 99久久亚洲综合精品成人网| 波多野结衣视频在线免费观看 | 成人福利免费视频| 精品免费久久久久久久| 国产四虎免费精品视频| a级毛片免费高清毛片视频| 久久青草精品38国产免费| 亚洲免费精彩视频在线观看| 8x8×在线永久免费视频| 亚洲成人免费网站|