注釋語法越來越多的被業界所使用,并且注釋配置相對于 XML 配置具有很多的優勢:它可以充分利用 Java 的反射機制獲取類結構信息,這些信息可以有效減少配置的工作。注釋和 Java 代碼位于一個文件中,而 XML 配置采用獨立的配置文件,大多數配置信息在程序開發完成后都不會調整,如果配置信息和 Java 代碼放在一起,有助于增強程序的內聚性。而采用獨立的 XML 配置文件,程序員在編寫一個功能時,往往需要在程序文件和配置文件中不停切換,這種思維上的不連貫會降低開發效率。因此在很多情況下,注釋配置比 XML 配置更受歡迎,注釋配置有進一步流行的趨勢。Spring 2.5 的一大增強就是引入了很多注釋類,現在您已經可以使用注釋配置完成大部分 XML 配置的功能。
首先,我們已經通過 傳統的spring +hibernate方式構架成功了一個應用的后臺體系。
這個體系里面 有這樣幾個重要的配置文件。
- hibernate.cfg.xml 。
里面通過 配置 mapping來指向每張數據表單生成配置文件.xxxx.hbm.xml文件 - applicaitonContex.xml。
里面通過定義一個一個bean 來配置 各個需要用到的 DAO 和 Service。 - <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
- <beans >
- <bean id="sessionFactory"
- class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
- <property name="configLocation"
- value="classpath:hibernate.cfg.xml">
- </property>
- </bean>
-
- <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
- <property name="sessionFactory">
- <ref local="sessionFactory"/>
- </property>
- </bean>
-
- <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
- <!-- 事務攔截器bean需要依賴注入一個事務管理器 -->
- <property name="transactionManager">
- <ref local="transactionManager"/>
- </property>
- <property name="transactionAttributes">
- <!-- 下面定義事務傳播屬性-->
- <props>
- <prop key="insert*">PROPAGATION_REQUIRED</prop>
- <prop key="update*">PROPAGATION_REQUIRED</prop>
- <prop key="save*">PROPAGATION_REQUIRED</prop>
- <prop key="add*">PROPAGATION_REQUIRED</prop>
- <prop key="update*">PROPAGATION_REQUIRED</prop>
- <prop key="remove*">PROPAGATION_REQUIRED</prop>
- <prop key="delete*">PROPAGATION_REQUIRED</prop>
- <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
- <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
- <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
- <prop key="change*">PROPAGATION_REQUIRED</prop>
- <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
- </props>
- </property>
- </bean>
-
-
- <!-- 定義自動代理BeanNameAutoProxyCreator -->
- <bean id="beanNameAutoProxyCreator"
- class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
- <!-- 指定對滿足哪些bean name的bean自動生成業務代理 -->
- <property name="beanNames">
- <list>
- <value>*Service</value>
- </list>
- </property>
- <!-- 下面定義BeanNameAutoProxyCreator所需的事務攔截器-->
- <property name="interceptorNames">
- <list>
- <!-- 此處可增加其他新的Interceptor -->
- <value>transactionInterceptor</value>
- </list>
- </property>
- </bean>
- <bean id="McCityInfoDAO"
- class="com.firemax.manatee.hibernate.McCityInfoDAO">
- <property name="sessionFactory">
- <ref bean="sessionFactory" />
- </property>
- </bean>
- <bean id="McMaterialInfoDAO"
- class="com.firemax.manatee.hibernate.McMaterialInfoDAO">
- <property name="sessionFactory">
- <ref bean="sessionFactory" />
- </property>
- </bean>
- </beans>
-
-
hibernate.cfg.xml要配置這么多 xxxxx.hbm.xml文件。每次數據結構發生變化的時候。要重新去改寫pojo和dao以及這些xxxxx.hbm.xml
那么好。我們現在就用 注解的力量 去把這部分工作簡化。
- hibernate3.2 以上版本的jar
- jdk 5 以上的環境
- spring2
- 然后我們修改pojo的java類。加上注解。使起通過注解來取代原先要xxxx.hbm.xml里面配置的指向的數據庫表單結構的信息。
- package com.alcor.web.hibernate;
-
- import java.util.HashSet;
- import java.util.Set;
- import javax.persistence.CascadeType;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.FetchType;
- import javax.persistence.Id;
- import javax.persistence.JoinColumn;
- import javax.persistence.ManyToOne;
- import javax.persistence.OneToMany;
- import javax.persistence.Table;
-
- /**
- * AlcorTCitys entity. @author MyEclipse Persistence Tools
- */
- @Entity
- @Table(name = "alcor_t_citys", catalog = "alcorweb")
- public class AlcorTCitys implements java.io.Serializable {
-
- // Fields
-
- private String cityCode;
- private AlcorTProvinces alcorTProvinces;
- private String cityName;
- private Set<AlcotTDistrict> alcotTDistricts = new HashSet<AlcotTDistrict>(0);
-
- // Constructors
-
- /** default constructor */
- public AlcorTCitys() {
- }
-
- /** minimal constructor */
- public AlcorTCitys(String cityCode, AlcorTProvinces alcorTProvinces,
- String cityName) {
- this.cityCode = cityCode;
- this.alcorTProvinces = alcorTProvinces;
- this.cityName = cityName;
- }
-
- /** full constructor */
- public AlcorTCitys(String cityCode, AlcorTProvinces alcorTProvinces,
- String cityName, Set<AlcotTDistrict> alcotTDistricts) {
- this.cityCode = cityCode;
- this.alcorTProvinces = alcorTProvinces;
- this.cityName = cityName;
- this.alcotTDistricts = alcotTDistricts;
- }
-
- // Property accessors
- @Id
- @Column(name = "city_code", unique = true, nullable = false, length = 32)
- public String getCityCode() {
- return this.cityCode;
- }
-
- public void setCityCode(String cityCode) {
- this.cityCode = cityCode;
- }
-
- @ManyToOne(fetch = FetchType.EAGER)
- @JoinColumn(name = "province_code", nullable = false)
- public AlcorTProvinces getAlcorTProvinces() {
- return this.alcorTProvinces;
- }
-
- public void setAlcorTProvinces(AlcorTProvinces alcorTProvinces) {
- this.alcorTProvinces = alcorTProvinces;
- }
-
- @Column(name = "city_name", nullable = false, length = 64)
- public String getCityName() {
- return this.cityName;
- }
-
- public void setCityName(String cityName) {
- this.cityName = cityName;
- }
-
- @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "alcorTCitys")
- public Set<AlcotTDistrict> getAlcotTDistricts() {
- return this.alcotTDistricts;
- }
-
- public void setAlcotTDistricts(Set<AlcotTDistrict> alcotTDistricts) {
- this.alcotTDistricts = alcotTDistricts;
- }
-
- }
- 修改hibernate.cfg.xml中的定義方式,把原來的maping source=“xxxxx.hbm.xml”修改成
<mapping class="com.alcor.web.hibernate.AlcorTCitys" />
這樣我們就可以把原來的 xxxxx.hbm.xml全部刪除了。
經過這個步驟。如果你原有的servcice層的功能能夠正常使用。恭喜你。邁出了成功的第一步
===============================================================================================
通過上面一步驟。我們簡化了hibernate中擾人的 xxxxx.hbm.xml文件。那么是否可以再進行簡化呢?
那么,我們在這一步驟的目的,就是把整個 hibernate.cfg.xml都給簡化了。
依然是利用注解注入的方式。通過jpa 我們可以把 hibernate.cfg.xml中那些 mapping classes再次簡化與無形。
- 在applicationContext.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 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
- xmlns:tx="http://www.springframework.org/schema/tx">
-
-
- <bean id="entityManagerFactory"
- class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
- <property name="persistenceUnitName" value="testerPU" />
- </bean>
- <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
- <property name="entityManagerFactory" ref="entityManagerFactory" />
- </bean>
-
- <tx:annotation-driven transaction-manager="transactionManager" />
-
- <bean id="transactionInterceptor"
- class="org.springframework.transaction.interceptor.TransactionInterceptor">
- <!-- 事務攔截器bean需要依賴注入一個事務管理器 -->
- <property name="transactionManager">
- <ref local="transactionManager" />
- </property>
- <property name="transactionAttributes">
- <!-- 下面定義事務(指service里面的方法)傳播屬性 -->
- <props>
- <prop key="insert*">PROPAGATION_REQUIRED</prop>
- <prop key="update*">PROPAGATION_REQUIRED</prop>
- <prop key="save*">PROPAGATION_REQUIRED</prop>
- <prop key="add*">PROPAGATION_REQUIRED</prop>
- <prop key="update*">PROPAGATION_REQUIRED</prop>
- <prop key="remove*">PROPAGATION_REQUIRED</prop>
- <prop key="delete*">PROPAGATION_REQUIRED</prop>
- <prop key="get*">PROPAGATION_REQUIRED,readOnly
- </prop>
- <prop key="find*">PROPAGATION_REQUIRED,readOnly
- </prop>
- <prop key="load*">PROPAGATION_REQUIRED,readOnly
- </prop>
- <prop key="change*">PROPAGATION_REQUIRED</prop>
- <prop key="count*">PROPAGATION_REQUIRED</prop>
- <prop key="*">PROPAGATION_REQUIRED</prop>
- </props>
- </property>
- </bean>
- <!-- 定義自動代理BeanNameAutoProxyCreator -->
- <bean id="beanNameAutoProxyCreator"
- class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
- <!-- 指定對滿足哪些bean name的bean自動生成業務代理 -->
- <property name="beanNames">
- <list>
- <value>*Service</value>
- </list>
- </property>
- <!-- 下面定義BeanNameAutoProxyCreator所需的事務攔截器 -->
- <property name="interceptorNames">
- <list>
- <!-- 此處可增加其他新的Interceptor -->
- <value>transactionInterceptor</value>
- </list>
- </property>
- </bean>
-
-
-
-
-
- <bean id="AlcorTCountriesDAO" class="com.firemax.test.hibernate.AlcorTCountriesDAO">
- <property name="entityManagerFactory" ref="entityManagerFactory" />
- </bean>
- <bean id="AlcorTProvincesDAO" class="com.firemax.test.hibernate.AlcorTProvincesDAO">
- <property name="entityManagerFactory" ref="entityManagerFactory" />
- </bean>
- <bean id="AlcotTDistrictDAO" class="com.firemax.test.hibernate.AlcotTDistrictDAO">
- <property name="entityManagerFactory" ref="entityManagerFactory" />
- </bean>
- <bean id="AlcorTCitysDAO" class="com.firemax.test.hibernate.AlcorTCitysDAO">
- <property name="entityManagerFactory" ref="entityManagerFactory" />
- </bean>
-
- <bean id="CountryService" class="com.firemax.test.service.CountryService">
- <property name="alcorTCountriesDAO" ref="AlcorTCountriesDAO" />
- <property name="alcorTProvincesDAO" ref="AlcorTProvincesDAO" />
- <property name="alcorTCitysDAO" ref="AlcorTCitysDAO" />
- <property name="alcotTDistrictDAO" ref="AlcotTDistrictDAO" />
- </bean>
-
- </beans>
注意紅色部分。這部分和(一)里面提到的那個applicationContext.xml中使用的bean是不同的。這里面已經用到了spring 的jpa部分。
其中 <property name="persistenceUnitName" value="testerPU" /> 是指向了一個 jpa的PU(Persistent Units)
那么這個 是在哪里定義的呢?
這里的定義是在你的 classes(src)目錄下META-INF下的persistence.xml文件中來定義
persistence.xml文件內容如下:
- <?xml version="1.0" encoding="UTF-8"?>
- <persistence xmlns="http://java.sun.com/xml/ns/persistence"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
- http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
- version="1.0">
-
- <persistence-unit name="testerPU"
- transaction-type="RESOURCE_LOCAL">
- <provider>org.hibernate.ejb.HibernatePersistence</provider>
- <class>com.firemax.test.hibernate.AlcorTCountries</class>
- <class>com.firemax.test.hibernate.AlcorTProvinces</class>
- <class>com.firemax.test.hibernate.AlcotTDistrict</class>
- <class>com.firemax.test.hibernate.AlcorTCitys</class>
- <properties>
- <property name="hibernate.connection.driver_class"
- value="com.mysql.jdbc.Driver" />
- <property name="hibernate.connection.url"
- value="jdbc:mysql://localhost:3306/alcorweb?useUnicode=true&characterEncoding=utf-8" />
- <property name="hibernate.connection.username"
- value="alcorweb" />
- <property name="hibernate.connection.password"
- value="alcorweb" />
- <property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider"/>
- <property name="hibernate.c3p0.max_size" value="100"/>
- <property name="hibernate.c3p0.min_size" value="20"/>
- <property name="hibernate.c3p0.timeout" value="120"/>
- <property name="hibernate.c3p0.max_statements" value="0"/>
- <property name="hibernate.c3p0.idle_test_period" value="120"/>
- <property name="hibernate.c3p0.acquire_increment" value="5 "/>
-
- <property name="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider"/>
- <property name="hibernate.cache.use_query_cache" value="false"/>
- <property name="hibernate.show_sql" value="false"/>
- <property name="hibernate.useUnicode" value="true"/>
- <property name="hibernate.characterEncoding" value="utf8"/>
- </properties>
- </persistence-unit>
- </persistence>
仔細觀察他的代碼,我們發現其實和hibernate.cfg.xml和相似。都有指向pojo的定義 和 database連接的定義。先別著急。我們這次的優化,就先完成這個目標。主要是引入的spring的jpa框架。
后面將介紹更進一步的優化。來展示jpa 和 注釋注入的能力。
- ===========================================================================
- 通過 (一),(二)的介紹。我們已經做了初步的簡化程序。
但是在我們編寫spring 框架的代碼時候。一直遵循是這樣一個規則:所有在spring中注入的bean 都建議定義成私有的域變量。并且要配套寫上 get 和 set方法。雖然 可以通過eclipse等工具來自動生成。但是還是會引起程序閱讀性上的不便。那么既然注解這么強大。是否可以也把他精簡掉呢?
當然可以。這個標簽就是@Autowired
Spring 2.5 引入了 @Autowired 注釋,它可以對類成員變量、方法及構造函數進行標注,完成自動裝配的工作。
要實現我們要精簡程序的目的。需要這樣來處理:
o 在applicationContext.xml中加入:
2. <!-- 該 BeanPostProcessor 將自動對標注 @Autowired 的 Bean 進行注入 -->
3. <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
o 修改在原來注入spirng容器中的bean的方法。在域變量上加上標簽@Autowired,并且去掉 相應的get 和set方法
1. /*國家,省份,城市,城區信息維護服務
2. * Created on 2008-9-26
3. *
4. * 徐澤宇 roamer
5. */
6. package com.firemax.test.service;
7.
8. import java.util.ArrayList;
9. import java.util.Iterator;
10. import java.util.List;
11.
12. import org.apache.commons.logging.Log;
13. import org.apache.commons.logging.LogFactory;
14. import org.dom4j.Document;
15. import org.dom4j.DocumentHelper;
16. import org.dom4j.Element;
17. import org.springframework.beans.factory.annotation.Autowired;
18.
19. import com.firemax.test.hibernate.AlcorTCitys;
20. import com.firemax.test.hibernate.AlcorTCitysDAO;
21. import com.firemax.test.hibernate.AlcorTCountries;
22. import com.firemax.test.hibernate.AlcorTCountriesDAO;
23. import com.firemax.test.hibernate.AlcorTProvinces;
24. import com.firemax.test.hibernate.AlcorTProvincesDAO;
25. import com.firemax.test.hibernate.AlcotTDistrict;
26. import com.firemax.test.hibernate.AlcotTDistrictDAO;
27.
28.
29. public class CountryService {
30. private static Log logger = LogFactory.getLog(CountryService.class);
31. @Autowired
32. private AlcorTCountriesDAO alcorTCountriesDAO;
33. @Autowired
34. private AlcorTProvincesDAO alcorTProvincesDAO;
35. @Autowired
36. private AlcorTCitysDAO alcorTCitysDAO;
37. @Autowired
38. private AlcotTDistrictDAO alcotTDistrictDAO;
39.
40. public CountryService(){
41.
42. }
43.
44. /**修改一個國家信息
45. * @param alcorTCountries
46. * @throws Exception
47. */
48. public void updateCountry(AlcorTCountries alcorTCountries ) throws Exception{
49. this.alcorTCountriesDAO.update(alcorTCountries);
50. }
51.
52. ....
53. //這里去掉了哪些DAO 變量的get 和set 方法。
54.
55.
56.
57.
58. }
59.
60.
o 在applicatonContext.xml中 把原來 引用的<porpery >標簽也去掉。
1. <bean id="CountryService" class="com.firemax.test.service.CountryService">
2. <property name="alcorTCountriesDAO" ref="AlcorTCountriesDAO" />
3. <property name="alcorTProvincesDAO" ref="AlcorTProvincesDAO" />
4. <property name="alcorTCitysDAO" ref="AlcorTCitysDAO" />
5. <property name="alcotTDistrictDAO" ref="AlcotTDistrictDAO" />
6. </bean>
修改成
7. <bean id="CountryService" class="com.firemax.test.service.CountryService">
8.
9. </bean>
當然,我們也可以在構造函數上使用@Auwowired 注解 。如果構造函數有兩個入參,分別是 bean1 和 bean2,@Autowired 將分別尋找和它們類型匹配的 Bean,將它們作為 CountryService (Bean1 bean1 ,Bean2 bean2) 的入參來創建 CountryService Bean。
在運行一下你的業務程序。如果沒有錯誤。恭喜你。這個步驟我們又完成了。
======================================================================
在(三)里面。我們引入了 <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>這個bean 來處理@Autowired注解。
其實在spring 里面還有其他三個BeanPostProcessor 。總共有四個,分別是:
AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
PersistenceAnnotationBeanPostProcessor
equiredAnnotationBeanPostProcessor
但是直接在 Spring 配置文件中定義這些 Bean 顯得比較笨拙。Spring 為我們提供了一種方便的注冊這些 BeanPostProcessor 的方式,這就是 <context:annotation-config/>
Spring 2.1 添加了一個新的 context 的 Schema 命名空間,該命名空間對注釋驅動、屬性文件引入、加載期織入等功能提供了便捷的配置。我們知道注釋本身是不會做任何事情的,它僅提供元數據信息。要使元數據信息真正起作用,必須讓負責處理這些元數據的處理器工作起來。
這段代碼就是 啟用了這個命名空間后的applicationContext.xml文件
0. <?xml version="1.0" encoding="UTF-8"?>
1. <beans xmlns="http://www.springframework.org/schema/beans"
2. xmlns:context="http://www.springframework.org/schema/context"
3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4. xmlns:tx="http://www.springframework.org/schema/tx"
5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
6. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
7. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
8. >
9.
10.
11. <bean id="entityManagerFactory"
12. class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
13. <property name="persistenceUnitName" value="testerPU" />
14. </bean>
15. <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
16. <property name="entityManagerFactory" ref="entityManagerFactory" />
17. </bean>
18.
19. <tx:annotation-driven transaction-manager="transactionManager" />
20.
21. <bean id="transactionInterceptor"
22. class="org.springframework.transaction.interceptor.TransactionInterceptor">
23. <!-- 事務攔截器bean需要依賴注入一個事務管理器 -->
24. <property name="transactionManager">
25. <ref local="transactionManager" />
26. </property>
27. <property name="transactionAttributes">
28. <!-- 下面定義事務(指service里面的方法)傳播屬性 -->
29. <props>
30. <prop key="insert*">PROPAGATION_REQUIRED</prop>
31. <prop key="update*">PROPAGATION_REQUIRED</prop>
32. <prop key="save*">PROPAGATION_REQUIRED</prop>
33. <prop key="add*">PROPAGATION_REQUIRED</prop>
34. <prop key="update*">PROPAGATION_REQUIRED</prop>
35. <prop key="remove*">PROPAGATION_REQUIRED</prop>
36. <prop key="delete*">PROPAGATION_REQUIRED</prop>
37. <prop key="get*">PROPAGATION_REQUIRED,readOnly
38. </prop>
39. <prop key="find*">PROPAGATION_REQUIRED,readOnly
40. </prop>
41. <prop key="load*">PROPAGATION_REQUIRED,readOnly
42. </prop>
43. <prop key="change*">PROPAGATION_REQUIRED</prop>
44. <prop key="count*">PROPAGATION_REQUIRED</prop>
45. <prop key="*">PROPAGATION_REQUIRED</prop>
46. </props>
47. </property>
48. </bean>
49.
50. <!-- 該 BeanPostProcessor 將自動對標注 @Autowired 的 Bean 進行注入 -->
51. <!-- 這個Processor 已經被 <context:annotation-config/> 所簡化
52. <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
53. -->
54. <context:annotation-config/>
55.
56.
57. <!-- 定義自動代理BeanNameAutoProxyCreator -->
58. <bean id="beanNameAutoProxyCreator"
59. class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
60. <!-- 指定對滿足哪些bean name的bean自動生成業務代理 -->
61. <property name="beanNames">
62. <list>
63. <value>*Service</value>
64. </list>
65. </property>
66. <!-- 下面定義BeanNameAutoProxyCreator所需的事務攔截器 -->
67. <property name="interceptorNames">
68. <list>
69. <!-- 此處可增加其他新的Interceptor -->
70. <value>transactionInterceptor</value>
71. </list>
72. </property>
73. </bean>
74.
75.
76.
77.
78.
79. <bean id="AlcorTCountriesDAO" class="com.firemax.test.hibernate.AlcorTCountriesDAO">
80. <property name="entityManagerFactory" ref="entityManagerFactory" />
81. </bean>
82. <bean id="AlcorTProvincesDAO" class="com.firemax.test.hibernate.AlcorTProvincesDAO">
83. <property name="entityManagerFactory" ref="entityManagerFactory" />
84. </bean>
85. <bean id="AlcotTDistrictDAO" class="com.firemax.test.hibernate.AlcotTDistrictDAO">
86. <property name="entityManagerFactory" ref="entityManagerFactory" />
87. </bean>
88. <bean id="AlcorTCitysDAO" class="com.firemax.test.hibernate.AlcorTCitysDAO">
89. <property name="entityManagerFactory" ref="entityManagerFactory" />
90. </bean>
91.
92. <bean id="CountryService" class="com.firemax.test.service.CountryService"/>
93.
94.
95. </beans>
注意2段標紅的內容,就是這次更新的配置內容。在配置文件中使用 context 命名空間之前,必須在 <beans> 元素中聲明 context 命名空間。
===========================================================================================
雖然我們可以通過 @Autowired 在 Bean 類中使用自動注入功能,但是 Bean 還是在 applicatonContext.xml 文件中通過 <bean> 進行定義 —— 在前面的例子中,我們還是在配置文件中定義 Bean,通過 @Autowired為 Bean 的成員變量、方法形參或構造函數形參提供自動注入的功能。
那么能不是也可以通過注解定義 Bean,從 XML 配置文件中完全移除 Bean 定義的配置呢?
答案是肯定的,我們通過 Spring 2.5 提供的 @Component 注釋就可以達到這個目標了。
修改Bean的java類的代碼如下,在類名前面加上 @Component注解
0. package com.firemax.test.service;
1.
2. import java.util.ArrayList;
3. import java.util.Iterator;
4. import java.util.List;
5.
6. import org.apache.commons.logging.Log;
7. import org.apache.commons.logging.LogFactory;
8. import org.dom4j.Document;
9. import org.dom4j.DocumentHelper;
10. import org.dom4j.Element;
11. import org.springframework.beans.factory.annotation.Autowired;
12. import org.springframework.stereotype.Component;
13.
14.
15. import com.firemax.test.hibernate.AlcorTCitys;
16. import com.firemax.test.hibernate.AlcorTCitysDAO;
17. import com.firemax.test.hibernate.AlcorTCountries;
18. import com.firemax.test.hibernate.AlcorTCountriesDAO;
19. import com.firemax.test.hibernate.AlcorTProvinces;
20. import com.firemax.test.hibernate.AlcorTProvincesDAO;
21. import com.firemax.test.hibernate.AlcotTDistrict;
22. import com.firemax.test.hibernate.AlcotTDistrictDAO;
23.
24. @Component
25. public class CountryService {
26. private static Log logger = LogFactory.getLog(CountryService.class);
27. @Autowired
28. private AlcorTCountriesDAO alcorTCountriesDAO;
29. @Autowired
30. private AlcorTProvincesDAO alcorTProvincesDAO;
31. @Autowired
32. private AlcorTCitysDAO alcorTCitysDAO;
33. @Autowired
34. private AlcotTDistrictDAO alcotTDistrictDAO;
35.
36. public CountryService(){
37.
38. }
39. //這里是業務邏輯的方法
40. 。。。。。
41. }
然后,我們修改配置文件applicatonContext.xml中,啟用自動注入的功能,而放棄原來的<bean>方式的配置
42. <?xml version="1.0" encoding="UTF-8"?>
43. <beans xmlns="http://www.springframework.org/schema/beans"
44. xmlns:context="http://www.springframework.org/schema/context"
45. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
46. xmlns:tx="http://www.springframework.org/schema/tx"
47. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
48. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
49. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
50. default-autowire="autodetect">
51. <bean id="entityManagerFactory"
52. class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
53. <property name="persistenceUnitName" value="testerPU" />
54. </bean>
55. <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
56. <property name="entityManagerFactory" ref="entityManagerFactory" />
57. </bean>
58. <tx:annotation-driven transaction-manager="transactionManager" />
59. <bean id="transactionInterceptor"
60. class="org.springframework.transaction.interceptor.TransactionInterceptor">
61. <!-- 事務攔截器bean需要依賴注入一個事務管理器 -->
62. <property name="transactionManager">
63. <ref local="transactionManager" />
64. </property>
65. <property name="transactionAttributes">
66. <!-- 下面定義事務(指service里面的方法)傳播屬性 -->
67. <props>
68. <prop key="insert*">PROPAGATION_REQUIRED</prop>
69. <prop key="update*">PROPAGATION_REQUIRED</prop>
70. <prop key="save*">PROPAGATION_REQUIRED</prop>
71. <prop key="add*">PROPAGATION_REQUIRED</prop>
72. <prop key="update*">PROPAGATION_REQUIRED</prop>
73. <prop key="remove*">PROPAGATION_REQUIRED</prop>
74. <prop key="delete*">PROPAGATION_REQUIRED</prop>
75. <prop key="get*">PROPAGATION_REQUIRED,readOnly
76. </prop>
77. <prop key="find*">PROPAGATION_REQUIRED,readOnly
78. </prop>
79. <prop key="load*">PROPAGATION_REQUIRED,readOnly
80. </prop>
81. <prop key="change*">PROPAGATION_REQUIRED</prop>
82. <prop key="count*">PROPAGATION_REQUIRED</prop>
83. <prop key="*">PROPAGATION_REQUIRED</prop>
84. </props>
85. </property>
86. </bean>
87.
88. <!-- 該 BeanPostProcessor 將自動對標注 @Autowired 的 Bean 進行注入 -->
89. <!-- 這個Processor 已經被 <context:annotation-config/> 所簡化
90. <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
91. -->
92. <!-- <context:component-scan/> 配置項不但啟用了對類包進行掃描以實施注釋驅動 Bean 定義的功能,同時還啟用了注釋驅動自動注入的功能(即還隱式地在內部注冊了 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor),因此當使用 <context:component-scan/> 后,就可以將 <context:annotation-config/> 移除了。 -->
93. <context:component-scan base-package ="com.firemax"/>
94.
95.
96. <!-- 定義自動代理BeanNameAutoProxyCreator -->
97. <bean id="beanNameAutoProxyCreator"
98. class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
99. <!-- 指定對滿足哪些bean name的bean自動生成業務代理 -->
100. <property name="beanNames">
101. <list>
102. <value>*Service</value>
103. </list>
104. </property>
105. <!-- 下面定義BeanNameAutoProxyCreator所需的事務攔截器 -->
106. <property name="interceptorNames">
107. <list>
108. <!-- 此處可增加其他新的Interceptor -->
109. <value>transactionInterceptor</value>
110. </list>
111. </property>
112. </bean>
113. <!--
114. <bean id="AlcorTCountriesDAO" class="com.firemax.test.hibernate.AlcorTCountriesDAO">
115. <property name="entityManagerFactory" ref="entityManagerFactory" />
116. </bean>
117. <bean id="AlcorTProvincesDAO" class="com.firemax.test.hibernate.AlcorTProvincesDAO">
118. <property name="entityManagerFactory" ref="entityManagerFactory" />
119. </bean>
120. <bean id="AlcotTDistrictDAO" class="com.firemax.test.hibernate.AlcotTDistrictDAO">
121. <property name="entityManagerFactory" ref="entityManagerFactory" />
122. </bean>
123. <bean id="AlcorTCitysDAO" class="com.firemax.test.hibernate.AlcorTCitysDAO">
124. <property name="entityManagerFactory" ref="entityManagerFactory" />
125. </bean>
126.
127. <bean id="CountryService" class="com.firemax.test.service.CountryService"/>
128. -->
129. </beans>
新的applicaitonContext.xml 配置文件中藍色的部分就是原來的<bean>的注入方式,現在已經給屏蔽了。不需要再寫。而紅色部分就是使用了<context:component-scan base-package ="com.firemax"/> ,讓spirng自動搜索,然后注入。
注意:
o 這里注入的bean 的名稱是按照類的名稱,把第一個字母改成小寫來命名的。比如例子中的CountryService的bean的名稱就是countryService.
o 我們也可以通過@Component("countryService") 這種方式來顯示的定義一個bean的注入名稱。但是在大多數情況下沒有必要。
<context:component-scan/> 的 base-package 屬性指定了需要掃描的類包,類包及其遞歸子包中所有的類都會被處理。
<context:component-scan/> 還允許定義過濾器將基包下的某些類納入或排除。Spring 支持以下 4 種類型的過濾方式,通過下表說明:
掃描過濾方式
過濾器類型 | 說明 |
注釋 | 假如 com.firemax.test.SomeAnnotation 是一個注釋類,我們可以將使用該注釋的類過濾出來。 |
類名指定 | 通過全限定類名進行過濾,如您可以指定將 com.firemax.test.IncludeService納入掃描,而將 com.firemax.test.NotIncludeService 排除在外。 |
正則表達式 | 通過正則表達式定義過濾的類,如下所示: com/.firemax/.test/.Default.* |
AspectJ 表達式 | 通過 AspectJ 表達式定義過濾的類,如下所示: com. firemax.test..*Service+ |
下面是一個簡單的例子:
默認情況下通過 @Component 定義的 Bean 都是 singleton 的,如果需要使用其它作用范圍的 Bean,可以通過 @Scope 注釋來達到目標,如以下代碼所示:
通過 @Scope 指定 Bean 的作用范圍
這樣,當從 Spring 容器中獲取 boss Bean 時,每次返回的都是新的實例了。
在Spring2.5中引入了更多的典型化注解,@Repository ,@Service,@Controler是@Component的細化。分別表示持久層,服務層,控制層。建議使用這個注解來取代@Component
附上一個java Applicaiton的簡單測試程序
132. /*
133. * Created on 2008-9-28
134. *
135. * 徐澤宇 roamer
136. */
137. package com.firemax.test.tester;
138.
139. import java.util.Iterator;
140.
141. import org.springframework.context.ApplicationContext;
142. import org.springframework.context.support.FileSystemXmlApplicationContext;
143.
144. import com.firemax.test.hibernate.AlcorTCitys;
145. import com.firemax.test.hibernate.AlcorTCitysDAO;
146. import com.firemax.test.hibernate.AlcorTCountries;
147. import com.firemax.test.hibernate.AlcorTProvinces;
148. import com.firemax.test.hibernate.AlcotTDistrict;
149. import com.firemax.test.hibernate.AlcotTDistrictDAO;
150. import com.firemax.test.service.CountryService;
151.
152.
153.
154. public class Tester {
155.
156. /**
157. * @param args
158. */
159. public static void main(String[] args) throws Exception{
160. // TODO Auto-generated method stub
161. ApplicationContext ctx = new FileSystemXmlApplicationContext("/WebContent/WEB-INF/classes/applicationContext*.xml");
162. String[] beans = ctx.getBeanDefinitionNames();
163. for (int i = 0 ; i < beans.length;i++)
164. {
165. System.out.println(beans[i]);
166. }
167. CountryService countryService= (CountryService)ctx.getBean("countryService");
168.
169. AlcorTCountries alcorTCountries= countryService.getCountriesInfo("CN");
170. System.out.println(alcorTCountries.getCountry());
171. System.out.println("開始調用子類");
172. System.out.println(alcorTCountries.getAlcorTProvinceses().size());
173. Iterator<AlcorTProvinces> it = alcorTCountries.getAlcorTProvinceses().iterator();
174. while (it.hasNext()){
175. AlcorTProvinces alcorTProvinces= (AlcorTProvinces)it.next();
176. System.out.println(alcorTProvinces.getProvinceName());
177. }
178. AlcotTDistrict alcotTDistrict= new AlcotTDistrict();
179. alcotTDistrict.setDistrictCode("22");
180. alcotTDistrict.setDistrictName("浦東");
181. AlcorTCitys alcorTCitys =countryService.getCityInfo("021");
182. alcotTDistrict.setAlcorTCitys(alcorTCitys);
183. countryService.saveProvinces(alcotTDistrict);
184.
185. }
186. }
187.
188.
在所有的JPOPO中,我們可以使用@Entity 這個注解來注入 JOPO。這樣我們在 Persistent.xml中就不需要在 定義哪些POJO的類了。
感謝 JPA 感謝Spring ,終于不要頻繁的去定義和修改這些Bean了