雖然我們可以通過 @Autowired 在 Bean 類中使用自動注入功能,但是 Bean 還是在 applicatonContext.xml 檔案中通過 <bean> 進行定義 —— 在前面的例子中,我們還是在配置檔案中定義 Bean,通過 @Autowired為 Bean 的成員變量、方法形參或構造函數形參提供自動注入的功能。 那麼能不是也可以通過注解定義 Bean,從 XML 配置檔案中完全移除 Bean 定義的配置呢? 答案是肯定的,我們通過 Spring 2.5 提供的 @Component 注釋就可以達到這個目标了。 修改Bean的java類的代碼如下,在類名前面加上 @Component注解
- package com.firemax.test.service;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.dom4j.Document;
- import org.dom4j.DocumentHelper;
- import org.dom4j.Element;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import com.firemax.test.hibernate.AlcorTCitys;
- import com.firemax.test.hibernate.AlcorTCitysDAO;
- import com.firemax.test.hibernate.AlcorTCountries;
- import com.firemax.test.hibernate.AlcorTCountriesDAO;
- import com.firemax.test.hibernate.AlcorTProvinces;
- import com.firemax.test.hibernate.AlcorTProvincesDAO;
- import com.firemax.test.hibernate.AlcotTDistrict;
- import com.firemax.test.hibernate.AlcotTDistrictDAO;
- @Component
- public class CountryService {
- private static Log logger = LogFactory.getLog(CountryService.class);
- @Autowired
- private AlcorTCountriesDAO alcorTCountriesDAO;
- @Autowired
- private AlcorTProvincesDAO alcorTProvincesDAO;
- @Autowired
- private AlcorTCitysDAO alcorTCitysDAO;
- @Autowired
- private AlcotTDistrictDAO alcotTDistrictDAO;
- public CountryService(){
- }
- //這裡是業務邏輯的方法
- 。。。。。
- }
然後,我們修改配置檔案applicatonContext.xml中,啟用自動注入的功能,而放棄原來的<bean>方式的配置
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:tx="http://www.springframework.org/schema/tx"
- 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
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
- default-autowire="autodetect">
- <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>
- <!-- 該 BeanPostProcessor 将自動對标注 @Autowired 的 Bean 進行注入 -->
- <!-- 這個Processor 已經被 <context:annotation-config/> 所簡化
- <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
- -->
- <!-- <context:component-scan/> 配置項不但啟用了對類包進行掃描以實施注釋驅動 Bean 定義的功能,同時還啟用了注釋驅動自動注入的功能(即還隐式地在内部注冊了 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor),是以當使用 <context:component-scan/> 後,就可以将 <context:annotation-config/> 移除了。 -->
- <context:component-scan base-package ="com.firemax"/>
- <!-- 定義自動代理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"/>
- -->
- </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+ |
下面是一個簡單的例子:
|
預設情況下通過
@Component
定義的 Bean 都是 singleton 的,如果需要使用其它作用範圍的 Bean,可以通過
@Scope
注釋來達到目标,如以下代碼所示:
通過 @Scope 指定 Bean 的作用範圍 |
這樣,當從 Spring 容器中擷取
boss
Bean 時,每次傳回的都是新的執行個體了。
在Spring2.5中引入了更多的典型化注解,@Repository ,@Service,@Controler是@Component的細化。分别表示持久層,服務層,控制層。建議使用這個注解來取代@Component
附上一個java Applicaiton的簡單測試程式
- package com.firemax.test.tester;
- import java.util.Iterator;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.FileSystemXmlApplicationContext;
- import com.firemax.test.hibernate.AlcorTCitys;
- import com.firemax.test.hibernate.AlcorTCitysDAO;
- import com.firemax.test.hibernate.AlcorTCountries;
- import com.firemax.test.hibernate.AlcorTProvinces;
- import com.firemax.test.hibernate.AlcotTDistrict;
- import com.firemax.test.hibernate.AlcotTDistrictDAO;
- import com.firemax.test.service.CountryService;
- public class Tester {
- public static void main(String[] args) throws Exception{
- // TODO Auto-generated method stub
- ApplicationContext ctx = new FileSystemXmlApplicationContext("/WebContent/WEB-INF/classes/applicationContext*.xml");
- String[] beans = ctx.getBeanDefinitionNames();
- for (int i = 0 ; i < beans.length;i++)
- {
- System.out.println(beans[i]);
- }
- CountryService countryService= (CountryService)ctx.getBean("countryService");
- AlcorTCountries alcorTCountries= countryService.getCountriesInfo("CN");
- System.out.println(alcorTCountries.getCountry());
- System.out.println("開始調用子類");
- System.out.println(alcorTCountries.getAlcorTProvinceses().size());
- Iterator<AlcorTProvinces> it = alcorTCountries.getAlcorTProvinceses().iterator();
- while (it.hasNext()){
- AlcorTProvinces alcorTProvinces= (AlcorTProvinces)it.next();
- System.out.println(alcorTProvinces.getProvinceName());
- }
- AlcotTDistrict alcotTDistrict= new AlcotTDistrict();
- alcotTDistrict.setDistrictCode("22");
- alcotTDistrict.setDistrictName("浦東");
- AlcorTCitys alcorTCitys =countryService.getCityInfo("021");
- alcotTDistrict.setAlcorTCitys(alcorTCitys);
- countryService.saveProvinces(alcotTDistrict);
- }
- }
在所有的JPOPO中,我們可以使用@Entity 這個注解來注入 JOPO。這樣我們在 Persistent.xml中就不需要在 定義哪些POJO的類了。
感謝 JPA 感謝Spring ,終于不要頻繁的去定義和修改這些Bean了