天天看點

注解的力量 -----Spring 2.5 JPA hibernate 使用方法的點滴整理(五):使用@Component 來簡化bean的配置

雖然我們可以通過 @Autowired 在 Bean 類中使用自動注入功能,但是 Bean 還是在 applicatonContext.xml 檔案中通過 <bean> 進行定義 —— 在前面的例子中,我們還是在配置檔案中定義 Bean,通過 @Autowired為 Bean 的成員變量、方法形參或構造函數形參提供自動注入的功能。 那麼能不是也可以通過注解定義 Bean,從 XML 配置檔案中完全移除 Bean 定義的配置呢? 答案是肯定的,我們通過 Spring 2.5 提供的 @Component 注釋就可以達到這個目标了。 修改Bean的java類的代碼如下,在類名前面加上 @Component注解

  1. package com.firemax.test.service;
  2. import java.util.ArrayList;
  3. import java.util.Iterator;
  4. import java.util.List;
  5. import org.apache.commons.logging.Log;
  6. import org.apache.commons.logging.LogFactory;
  7. import org.dom4j.Document;
  8. import org.dom4j.DocumentHelper;
  9. import org.dom4j.Element;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.stereotype.Component;
  12. import com.firemax.test.hibernate.AlcorTCitys;
  13. import com.firemax.test.hibernate.AlcorTCitysDAO;
  14. import com.firemax.test.hibernate.AlcorTCountries;
  15. import com.firemax.test.hibernate.AlcorTCountriesDAO;
  16. import com.firemax.test.hibernate.AlcorTProvinces;
  17. import com.firemax.test.hibernate.AlcorTProvincesDAO;
  18. import com.firemax.test.hibernate.AlcotTDistrict;
  19. import com.firemax.test.hibernate.AlcotTDistrictDAO;
  20. @Component
  21. public class CountryService {
  22.     private static Log logger = LogFactory.getLog(CountryService.class);
  23.     @Autowired
  24.     private AlcorTCountriesDAO  alcorTCountriesDAO;
  25.     @Autowired
  26.     private AlcorTProvincesDAO  alcorTProvincesDAO;
  27.     @Autowired
  28.     private AlcorTCitysDAO          alcorTCitysDAO;
  29.     @Autowired
  30.     private AlcotTDistrictDAO       alcotTDistrictDAO;
  31.     public CountryService(){
  32.     }
  33.      //這裡是業務邏輯的方法
  34.      。。。。。
  35. }

然後,我們修改配置檔案applicatonContext.xml中,啟用自動注入的功能,而放棄原來的<bean>方式的配置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3.     xmlns:context="http://www.springframework.org/schema/context"
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5.     xmlns:tx="http://www.springframework.org/schema/tx"
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  7.                                             http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-2.5.xsd
  8.                                             http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
  9.     default-autowire="autodetect">
  10.     <bean id="entityManagerFactory"
  11.         class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
  12.         <property name="persistenceUnitName" value="testerPU" />
  13.     </bean>
  14.     <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
  15.         <property name="entityManagerFactory" ref="entityManagerFactory" />
  16.     </bean>
  17.     <tx:annotation-driven transaction-manager="transactionManager" />
  18.     <bean id="transactionInterceptor"
  19.         class="org.springframework.transaction.interceptor.TransactionInterceptor">
  20.         <!-- 事務攔截器bean需要依賴注入一個事務管理器 -->
  21.         <property name="transactionManager">
  22.             <ref local="transactionManager" />
  23.         </property>
  24.         <property name="transactionAttributes">
  25.             <!-- 下面定義事務(指service裡面的方法)傳播屬性 -->
  26.             <props>
  27.                 <prop key="insert*">PROPAGATION_REQUIRED</prop>
  28.                 <prop key="update*">PROPAGATION_REQUIRED</prop>
  29.                 <prop key="save*">PROPAGATION_REQUIRED</prop>
  30.                 <prop key="add*">PROPAGATION_REQUIRED</prop>
  31.                 <prop key="update*">PROPAGATION_REQUIRED</prop>
  32.                 <prop key="remove*">PROPAGATION_REQUIRED</prop>
  33.                 <prop key="delete*">PROPAGATION_REQUIRED</prop>
  34.                 <prop key="get*">PROPAGATION_REQUIRED,readOnly
  35.                 </prop>
  36.                 <prop key="find*">PROPAGATION_REQUIRED,readOnly
  37.                 </prop>
  38.                 <prop key="load*">PROPAGATION_REQUIRED,readOnly
  39.                 </prop>
  40.                 <prop key="change*">PROPAGATION_REQUIRED</prop>
  41.                 <prop key="count*">PROPAGATION_REQUIRED</prop>
  42.                 <prop key="*">PROPAGATION_REQUIRED</prop>
  43.             </props>
  44.         </property>
  45.     </bean>
  46.     <!-- 該 BeanPostProcessor 将自動對标注 @Autowired 的 Bean 進行注入 -->
  47.     <!--  這個Processor 已經被 <context:annotation-config/> 所簡化   
  48.     <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
  49.     -->
  50.      <!-- <context:component-scan/> 配置項不但啟用了對類包進行掃描以實施注釋驅動 Bean 定義的功能,同時還啟用了注釋驅動自動注入的功能(即還隐式地在内部注冊了 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor),是以當使用 <context:component-scan/> 後,就可以将 <context:annotation-config/> 移除了。 -->
  51.     <context:component-scan base-package ="com.firemax"/>  
  52.     <!-- 定義自動代理BeanNameAutoProxyCreator -->
  53.     <bean id="beanNameAutoProxyCreator"
  54.         class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
  55.         <!-- 指定對滿足哪些bean name的bean自動生成業務代理 -->
  56.         <property name="beanNames">
  57.             <list>
  58.                 <value>*Service</value>
  59.             </list>
  60.         </property>
  61.         <!-- 下面定義BeanNameAutoProxyCreator所需的事務攔截器  -->
  62.         <property name="interceptorNames">
  63.             <list>
  64.                 <!-- 此處可增加其他新的Interceptor -->
  65.                 <value>transactionInterceptor</value>
  66.             </list>
  67.         </property>
  68.     </bean>
  69.     <!-- 
  70.     <bean id="AlcorTCountriesDAO" class="com.firemax.test.hibernate.AlcorTCountriesDAO">
  71.         <property name="entityManagerFactory" ref="entityManagerFactory" />
  72.     </bean>
  73.     <bean id="AlcorTProvincesDAO" class="com.firemax.test.hibernate.AlcorTProvincesDAO">
  74.         <property name="entityManagerFactory" ref="entityManagerFactory" />
  75.     </bean>
  76.     <bean id="AlcotTDistrictDAO" class="com.firemax.test.hibernate.AlcotTDistrictDAO">
  77.         <property name="entityManagerFactory" ref="entityManagerFactory" />
  78.     </bean>
  79.     <bean id="AlcorTCitysDAO" class="com.firemax.test.hibernate.AlcorTCitysDAO">
  80.         <property name="entityManagerFactory" ref="entityManagerFactory" />
  81.     </bean>
  82.      <bean id="CountryService" class="com.firemax.test.service.CountryService"/>
  83.     -->
  84. </beans>

新的applicaitonContext.xml 配置檔案中藍色的部分就是原來的<bean>的注入方式,現在已經給屏蔽了。不需要再寫。而紅色部分就是使用了<context:component-scan base-package ="com.firemax"/> ,讓spirng自動搜尋,然後注入。

注意:

  • 這裡注入的bean 的名稱是按照類的名稱,把第一個字母改成小寫來命名的。比如例子中的CountryService的bean的名稱就是countryService.
  • 我們也可以通過@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+

下面是一個簡單的例子:

  1. <context:component-scan base-package="com.firemax">
  2.     <context:include-filter type="regex" 
  3.         expression="com/.firemax/.test/.service/..*"/>
  4.     <context:exclude-filter type="aspectj" 
  5.         expression="com.firemax.test.util..*"/>
  6. </context:component-scan>

預設情況下通過 

@Component

 定義的 Bean 都是 singleton 的,如果需要使用其它作用範圍的 Bean,可以通過 

@Scope

 注釋來達到目标,如以下代碼所示:

 通過 @Scope 指定 Bean 的作用範圍
  1. package com.firemax.tester.service;
  2. import org.springframework.context.annotation.Scope;
  3. @Scope("prototype")
  4. @Component("countryService")
  5. public class CountryService{
  6.     …
  7. }

這樣,當從 Spring 容器中擷取 

boss

 Bean 時,每次傳回的都是新的執行個體了。

在Spring2.5中引入了更多的典型化注解,@Repository ,@Service,@Controler是@Component的細化。分别表示持久層,服務層,控制層。建議使用這個注解來取代@Component

附上一個java Applicaiton的簡單測試程式

  1. package com.firemax.test.tester;
  2. import java.util.Iterator;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.FileSystemXmlApplicationContext;
  5. import com.firemax.test.hibernate.AlcorTCitys;
  6. import com.firemax.test.hibernate.AlcorTCitysDAO;
  7. import com.firemax.test.hibernate.AlcorTCountries;
  8. import com.firemax.test.hibernate.AlcorTProvinces;
  9. import com.firemax.test.hibernate.AlcotTDistrict;
  10. import com.firemax.test.hibernate.AlcotTDistrictDAO;
  11. import com.firemax.test.service.CountryService;
  12. public class Tester {
  13.     public static void main(String[] args) throws Exception{
  14.         // TODO Auto-generated method stub
  15.         ApplicationContext ctx =     new FileSystemXmlApplicationContext("/WebContent/WEB-INF/classes/applicationContext*.xml");
  16.         String[] beans = ctx.getBeanDefinitionNames();
  17.         for (int i = 0 ; i < beans.length;i++)
  18.         {
  19.             System.out.println(beans[i]);
  20.         }
  21.         CountryService countryService= (CountryService)ctx.getBean("countryService");
  22.         AlcorTCountries  alcorTCountries= countryService.getCountriesInfo("CN");
  23.         System.out.println(alcorTCountries.getCountry());
  24.         System.out.println("開始調用子類");
  25.         System.out.println(alcorTCountries.getAlcorTProvinceses().size());
  26.         Iterator<AlcorTProvinces> it = alcorTCountries.getAlcorTProvinceses().iterator();
  27.         while (it.hasNext()){
  28.             AlcorTProvinces  alcorTProvinces= (AlcorTProvinces)it.next();
  29.             System.out.println(alcorTProvinces.getProvinceName());
  30.         }
  31.         AlcotTDistrict alcotTDistrict= new AlcotTDistrict();
  32.         alcotTDistrict.setDistrictCode("22");
  33.         alcotTDistrict.setDistrictName("浦東");
  34.         AlcorTCitys alcorTCitys =countryService.getCityInfo("021");
  35.         alcotTDistrict.setAlcorTCitys(alcorTCitys);
  36.         countryService.saveProvinces(alcotTDistrict);
  37.     }
  38. }

在所有的JPOPO中,我們可以使用@Entity 這個注解來注入 JOPO。這樣我們在 Persistent.xml中就不需要在 定義哪些POJO的類了。

感謝 JPA 感謝Spring ,終于不要頻繁的去定義和修改這些Bean了

繼續閱讀