国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Spring JSR-250注解

Spring JSR-250注解

注釋配置相對(duì)于 XML 配置具有很多的優(yōu)勢(shì):

  • 它可以充分利用 Java 的反射機(jī)制獲取類結(jié)構(gòu)信息,這些信息可以有效減少配置的工作。如使用 JPA 注釋配置 ORM 映射時(shí),我們就不需要指定 PO 的屬性名、類型等信息,如果關(guān)系表字段和 PO 屬性名、類型都一致,您甚至無(wú)需編寫任務(wù)屬性映射信息——因?yàn)檫@些信息都可以通過 Java 反射機(jī)制獲取。
  • 注釋和 Java 代碼位于一個(gè)文件中,而 XML 配置采用獨(dú)立的配置文件,大多數(shù)配置信息在程序開發(fā)完成后都不會(huì)調(diào)整,如果配置信息和 Java 代碼放在一起,有助于增強(qiáng)程序的內(nèi)聚性。而采用獨(dú)立的 XML 配置文件,程序員在編寫一個(gè)功能時(shí),往往需要在程序文件和配置文件中不停切換,這種思維上的不連貫會(huì)降低開發(fā)效率。

因此在很多情況下,注釋配置比 XML 配置更受歡迎,注釋配置有進(jìn)一步流行的趨勢(shì)。Spring 2.5 的一大增強(qiáng)就是引入了很多注釋類,現(xiàn)在您已經(jīng)可以使用注釋配置完成大部分 XML 配置的功能。在這篇文章里,我們將向您講述使用注釋進(jìn)行 Bean 定義和依賴注入的內(nèi)容。

Java EE5中引入了“Java平臺(tái)的公共注解(Common Annotations for the Java Platform)”,而且該公共注解從Java SE 6一開始就被包含其中。 2006年5月,BEA系統(tǒng)宣布了他們?cè)谝粋€(gè)名為Pitchfork的項(xiàng)目上與Interface21的合作,該項(xiàng)目提供了基于Spring的Java EE 5編程模型的實(shí)現(xiàn),包括支持用于注入(injection)、攔截( interception)和事務(wù)處理(transactions)的JSR-250注解和EJB 3注解(JSR-220)。 在2.5版本中,Spring框架的核心(core)現(xiàn)在支持以下JSR-250注解:

  • @Resource
  • @PostConstruct
  • @PreDestroy

結(jié)合Spring,這些注解在任何開發(fā)環(huán)境下都可以使用——無(wú)論是否有應(yīng)用程序服務(wù)器——甚至是集成測(cè)試環(huán)境都可以。激活這樣的支持僅僅是注冊(cè)一個(gè)單獨(dú)的Spring post-processor的事情:

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

@Resource注解

@Resource 注解被用來(lái)激活一個(gè)命名資源(named resource)的依賴注入,在JavaEE應(yīng)用程序中,該注解被典型地轉(zhuǎn)換為綁定于JNDI context中的一個(gè)對(duì)象。 Spring確實(shí)支持使用@Resource通過JNDI lookup來(lái)解析對(duì)象,默認(rèn)地,擁有與@Resource注解所提供名字相匹配的“bean name(bean名字)”的Spring管理對(duì)象會(huì)被注入。 在下面的例子中,Spring會(huì)向加了注解的setter方法傳遞bean名為“dataSource”的Spring管理對(duì)象的引用。

@Resource(name="dataSource")
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
 

直接使用@Resource注解一個(gè)域(field)同樣是可能的。通過不暴露setter方法,代碼愈發(fā)緊湊并且還提供了域不可修改的額外益處。正如下面將要證明的,@Resource注解甚至不需要一個(gè)顯式的字符串值,在沒有提供任何值的情況下,域名將被當(dāng)作默認(rèn)值。

@Resource
private DataSource dataSource; // inject the bean named 'dataSource' 

該方式被應(yīng)用到setter方法的時(shí)候,默認(rèn)名是從相應(yīng)的屬性衍生出來(lái),換句話說(shuō),命名為'setDataSource'的方法被用來(lái)處理名為'dataSource'的屬性。

private DataSource dataSource;
@Resource
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
 

當(dāng)@Resource沒有顯式提供名字的時(shí)候,如果根據(jù)默認(rèn)名字找不到對(duì)應(yīng)的Spring管理對(duì)象,注入機(jī)制會(huì)回滾至類型匹配(type-match)。如果剛好只有一個(gè)Spring管理對(duì)象符合該依賴的類型,那么它會(huì)被注入。通過設(shè)置CommonAnnotationBeanPostProcessor‘fallbackToDefaultTypeMatch’屬性為“false”(默認(rèn)值是“true”)可以禁用這一特性。

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
<property name="fallbackToDefaultTypeMatch" value="false"/>
</bean> 

正如上文所提到的,在解析標(biāo)有@Resource注解的依賴時(shí),Spring支持JNDI-lookup。如若要強(qiáng)制對(duì)所有使用@Resource注解的依賴進(jìn)行JNDI lookup,那也只要將CommonAnnotationBeanPostProcessor'alwaysUseJndiLookup' 標(biāo)識(shí)設(shè)置為true就可以了(默認(rèn)值是false)。

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
<property name="alwaysUseJndiLookup" value="true"/>
</bean>

另一個(gè)選擇是,激活指定為‘resource-ref-mappings’的依據(jù)全局JNDI名的查找,在@Resource注解內(nèi)提供‘mappedName’屬性。即使目標(biāo)對(duì)象實(shí)際上是一個(gè)JNDI資源,仍然推薦引入一個(gè)Spring管理對(duì)象,這樣可以提供一個(gè)間接層并且因此降低耦合程度。自Spring2.0開始添加命名空間以來(lái),定義一個(gè)委托Spring處理JNDI lookup的bean也變得愈發(fā)簡(jiǎn)練:

<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/petclinic"/> 

這個(gè)方法的優(yōu)點(diǎn)在于間接層帶來(lái)了巨大的部署彈性。比如說(shuō),一個(gè)單獨(dú)的系統(tǒng)測(cè)試環(huán)境應(yīng)該不再需要JNDI注冊(cè)。在這種情況下,在系統(tǒng)測(cè)試配置中可以提供如下的bean定義:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName
="${jdbc.driverClassName}"
p:url
="${jdbc.url}"
p:username
="${jdbc.username}"
p:password
="${jdbc.password}"/> 

順便提一下,上面的例子中,實(shí)際的JDBC連接屬性從一個(gè)屬性文件(properties file)解析而來(lái),在這個(gè)屬性文件里,關(guān)鍵字與提供的${占位符}互相對(duì)應(yīng),這需要注冊(cè)一個(gè)名為PropertyPlaceholderConfigurerBeanFactoryPostProcessor實(shí)現(xiàn)來(lái)完成。這是具體化那些屬性(通常是針對(duì)特定環(huán)境的屬性)常用的技術(shù),這些屬性可能比其他配置修改得更為頻繁。

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties"/>
</bean> 

Srping2.5中新加入了‘context’命名空間,這個(gè)命名空間讓我們能夠得到更為簡(jiǎn)潔的方式來(lái)實(shí)現(xiàn)屬性占位符(property placeholder)的配置:

<context:property-placeholder location="classpath:jdbc.properties"/>

生命周期注解:@PostConstruct和@PreDestroy

@PostConstruct@PreDestroy注解分別用來(lái)觸發(fā)Spring的初始化和銷毀回調(diào)。這個(gè)特性在原有基礎(chǔ)上得到了擴(kuò)展,但并沒有替代在Spring2.5之前版本中提供的同樣的回調(diào)的另兩個(gè)選項(xiàng)。第一個(gè)選項(xiàng)是實(shí)現(xiàn)Spring的InitializingBeanDisposableBean 接口中的一個(gè)或兩個(gè)。這兩個(gè)接口都需要一個(gè)回調(diào)方法的實(shí)現(xiàn)(分別是afterPropertiesSet()destroy() )。這種基于接口的方法利用了Spring自動(dòng)識(shí)別任何實(shí)現(xiàn)這些接口的Spring管理對(duì)象的能力,因而不再需要另外的配置。另一方面,Spring的一個(gè)關(guān)鍵目標(biāo)是盡可能的非侵入。因此,許多Spring用戶并不采用實(shí)現(xiàn)這些Spring特定接口的方法,而利用第二個(gè)選項(xiàng),那就是提供他們自己的初始化和銷毀方法。盡管入侵性小,但缺點(diǎn)在于使用這個(gè)方式的話就必須顯式聲明bean元素的init-methoddestroy-method屬性。顯式配置有時(shí)候是必須的,例如當(dāng)回調(diào)需要在開發(fā)人員控制能力之外的代碼上被調(diào)用的時(shí)候。PetClinic應(yīng)用程序很好地說(shuō)明了這個(gè)場(chǎng)景。當(dāng)它和JDBC配置一起運(yùn)行的時(shí)候,會(huì)用到一個(gè)第三方DataSource,并且它顯式聲明了一個(gè)destroy-method。另外要注意到的是,單獨(dú)的連接池?cái)?shù)據(jù)源是dataSource的另一個(gè)部署選項(xiàng),并且不需要修改任何代碼。

<bean id="dataSource"
class
="org.apache.commons.dbcp.BasicDataSource"
destroy-method
="close"
p:driverClassName
="${jdbc.driverClassName}"
p:url
="${jdbc.url}"
p:username
="${jdbc.username}"
p:password
="${jdbc.password}"/> 

在使用Spring2.5的過程中,如果一個(gè)對(duì)象需要調(diào)用一個(gè)初始化的回調(diào)方法的話,這個(gè)回調(diào)方法可以采用@PostConstruct來(lái)注解。例如一個(gè)假想的例子,一個(gè)后臺(tái)任務(wù)需要在啟動(dòng)的時(shí)候就開始對(duì)一個(gè)文件目錄進(jìn)行輪詢:

public class FilePoller {

  @PostConstruct
  
public void startPolling() {
    

  }

  

}
 

類似地,一個(gè)在Spring管理對(duì)象上用@PreDestroy注解的方法會(huì)在這個(gè)對(duì)象寄宿的應(yīng)用程序上下文(application context)關(guān)閉的時(shí)候被調(diào)用。

public class FilePoller {

@PreDestroy
public void stopPolling() {

}


}
 

在添加了對(duì)JSR-250注解的支持以后,現(xiàn)在的Spring2.5結(jié)合前面提到的兩種生命周期方法的長(zhǎng)處。將@PostConstruct@PreDestroy作為方法層注解加入,足可以實(shí)現(xiàn)在受Spring管理的上下文(context)中觸發(fā)回調(diào)。換句話說(shuō),不需要另外基于XML的配置。同時(shí),這兩個(gè)注解是Java語(yǔ)言本身的一部分(甚至被包括在Java SE 版本6中),所以無(wú)需引入特定Spring包。這兩個(gè)注解擁有在其他環(huán)境中也能理解的標(biāo)識(shí)語(yǔ)義的優(yōu)點(diǎn),隨著時(shí)間的推移,Java開發(fā)人員可能會(huì)發(fā)現(xiàn)這些注解在第三方開發(fā)庫(kù)中被越來(lái)越多的運(yùn)用到。最后,基于注解生命周期回調(diào)的其中一個(gè)有趣的結(jié)果是,不止一個(gè)方法可以帶有這兩個(gè)注解中的任何一個(gè),并且所有注解了的方法會(huì)被調(diào)用。

激活剛剛描述的關(guān)于@Resource 、@PostConstruct@PreDestroy注解的所有行為,正如上文提到的,需要為Spring的CommonAnnotationBeanPostProcessor提供一個(gè)bean定義。但另一個(gè)更簡(jiǎn)練的方法則可能是使用2.5中的新的context命名空間:

<context:annotation-config/>

引入這個(gè)單個(gè)元素將不單單注冊(cè)一個(gè)CommonAnnotationBeanPostProcessor,也會(huì)像下文將敘述的那樣激活自動(dòng)裝配(autowire)行為。CommonAnnotationBeanPostProcessor也為@WebServiceRef@EJB注解提供支持。這些將在本文系列的第三篇中和Spring2.5為企業(yè)集成提供的其他新特性一起討論。

利用注解來(lái)優(yōu)化細(xì)粒度自動(dòng)裝配

涵蓋Spring對(duì)自動(dòng)裝配支持的文檔中常常會(huì)提到由于自動(dòng)裝配機(jī)制的粗粒度而伴隨有很多限制性。Spring2.5之前,自動(dòng)裝配可以通過很多不同的方式來(lái)配置:構(gòu)造器,類型setter,名字setter,或者自動(dòng)偵測(cè)(在該方式中Spring選擇自動(dòng)裝配一個(gè)構(gòu)造器或者類型setter)。這些不同的選擇確實(shí)提供了很大程度的靈活性,但它們中沒有一個(gè)方法能夠提供細(xì)粒度控制。換句話說(shuō),Spring2.5之前還不可能自動(dòng)裝配某個(gè)對(duì)象setter方法的特定子集,或者通過類型或名字來(lái)自動(dòng)裝配它的一些屬性。結(jié)果,許多Spring用戶意識(shí)到將自動(dòng)裝配應(yīng)用到構(gòu)建原型和測(cè)試中的好處,但當(dāng)提到在產(chǎn)品中維護(hù)和支持系統(tǒng)時(shí),大部分人認(rèn)為,加入冗長(zhǎng)的顯式配置對(duì)于澄清它所擔(dān)負(fù)的職責(zé)是非常值得的。

然而,Spring2.5大幅度地改變了布局。如上文所述,自動(dòng)配置選項(xiàng)現(xiàn)在已經(jīng)被擴(kuò)展,支持JSR-250 @Resource注解來(lái)激活在每個(gè)方法或域基礎(chǔ)上被命名資源的自動(dòng)裝配。然而,@Resource注解若單獨(dú)使用的話有很多限制。因此,Sring2.5引進(jìn)了一個(gè)名為@Autowired的注解進(jìn)一步提高控制級(jí)別。為激活這里所講的行為需要注冊(cè)一個(gè)單獨(dú)的bean定義:

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

另外如上文提到的,context命名空間提供了一個(gè)更簡(jiǎn)明的方法。它將激活本文所討論的兩個(gè)post-processor(AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor)和我們?cè)赟pring2.0中引入的基于注解的post-processor:RequiredAnnotationBeanPostProcessorPersistenceAnnotationBeanPostProcessor。

<context:annotation-config/>

利用@Autowired 注解可以對(duì)相應(yīng)類型注入依賴。域、構(gòu)造器和方法都可以激活此行為。實(shí)際上,aotowired方法并不一定要是setter方法,且可以接受多個(gè)參數(shù)。下面這個(gè)例子是完整的可接受的用法:

@Autowired
public void setup(DataSource dataSource, AnotherObject o) 
 }
 

默認(rèn)地,標(biāo)有@Autowired注解的依賴被認(rèn)為是必須的。然而,也可以將required屬性值設(shè)置為false來(lái)聲明它們中的任何一個(gè)。在下面這個(gè)例子中,DefaultStrategy只有在context命名空間中沒有SomeStrategy類型的Spring管理對(duì)象時(shí)才能被使用。

@Autowired(required=false)
private SomeStrategy strategy = new DefaultStrategy(); 

通過類型進(jìn)行的自動(dòng)裝配明顯地在Spring context包含多于一個(gè)期望類型的對(duì)象的時(shí)候造成歧義。默認(rèn)地,如果一個(gè)必須的依賴沒不是恰好一個(gè)bean與之對(duì)應(yīng)的話,自動(dòng)裝配機(jī)制就會(huì)失敗。同樣的,對(duì)于任何一個(gè)可選屬性,如果它擁有一個(gè)以上的候選,也都會(huì)失?。ㄈ绻麑傩钥蛇x且沒有任何候選可用的話,該屬性則會(huì)被簡(jiǎn)單地跳過)。有很多不同的配置選項(xiàng)可以避免這些沖突。

若Context中擁有一個(gè)指定類型的一個(gè)主關(guān)鍵實(shí)例,對(duì)這個(gè)類型定義的bean定義應(yīng)該包含‘primary’屬性。當(dāng)Context中含有其他可用實(shí)例的時(shí)候這個(gè)方法就很適用,但那些非主關(guān)鍵實(shí)例總是顯式配置的。

<bean id="dataSource" primary="true" 
 
/> 

在需要更多控制的時(shí)候,任何autowired的域、構(gòu)造參數(shù)、或者方法參數(shù)可以進(jìn)一步加注@Qualifier注解。qualifier可以包含一個(gè)字符串值,在這種情況下,Spring會(huì)試圖通過名字來(lái)找到對(duì)應(yīng)的對(duì)象。

@Autowired
@Qualifier(
"primaryDataSource")
private DataSource dataSource; 

@Qualifier作為一個(gè)獨(dú)立注解存在的主要原因是它可以被應(yīng)用在構(gòu)造器參數(shù)或方法參數(shù)上,但上文提到的@Autowired注解只能運(yùn)用在構(gòu)造器或方法本身。

@Autowired
public void setup(@Qualifier("primaryDataSource") DataSource dataSource, AnotherObject o) 
 }
 

事實(shí)上,@Qualifier作為一個(gè)單獨(dú)的注解在定制化方面提供了更多的好處。用戶自定義的注解在自動(dòng)裝配過程中也可以起到qualifier的作用,最簡(jiǎn)單的實(shí)現(xiàn)方式是在運(yùn)用自定義注解的同時(shí)將@Qualifier作為它的元注解。

@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface VetSpecialty 
 }
 

自定義注解可以選擇包含一個(gè)值來(lái)提供通過名字匹配的功能,但更普遍的用法是將它作為“標(biāo)記”注解或定義一個(gè)對(duì)qualifier過程提供一些更多含義的值。例如,下面這個(gè)摘錄則描繪了一個(gè)域,它應(yīng)該和通過名字匹配得到的結(jié)果中合格的對(duì)象進(jìn)行自動(dòng)裝配。

@Autowired
@VetSpecialty(
"dentistry")
private Clinic dentistryClinic; 

在使用XML配置來(lái)達(dá)到依賴解析的目標(biāo)時(shí),'qualifier' 子元素可以被加注到bean定義中。在下文的組件掃描部分,我們將呈現(xiàn)一個(gè)可供選擇的非XML方法。

<bean id="dentistryClinic" class="samples.DentistryClinic">
<qualifier type="example.VetSpecialty" value="dentistry"/>
</bean> 

為了避免對(duì)@Qualifier注解的任何依賴性,可以在Spring context中提供一個(gè)CustomAutowireConfigurer的bean定義并直接注冊(cè)所有自定義注解類型:

<bean class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>example.VetSpecialty</value>
</set>
</property>
</bean> 

現(xiàn)在,自定義修飾符被顯式聲明了,就不再需要@Qualifier這個(gè)元注解符了。

@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface VetSpecialty 
 }
 

其實(shí),在配置AutowiredAnnotationBeanPostProcessor的時(shí)候,取代@Autowired注解都是有可能的。

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor">
<property name="autowiredAnnotationType" value="example.Injected"/>
</bean> 

大部分情況下,定義自定義‘標(biāo)記’注解的能力結(jié)合通過名字或其他文法值進(jìn)行匹配選項(xiàng),足以完成自動(dòng)裝配過程的細(xì)粒度控制。但Spring還支持在qualifier注解上任意數(shù)目的任意屬性。比如,下面是一個(gè)極為細(xì)粒度修飾的例子。

@SpecializedClinic(species="dog", breed="poodle")
private Clinic poodleClinic; 

自定義修飾符的實(shí)現(xiàn)應(yīng)該定義這些屬性:

@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface SpecializedClinic {

String species();

String breed();

}
 

自定義修飾符屬性可以匹配那些XML中bean定義的qualifier注解的屬性子元素。這些元素通常以鍵/值對(duì)方式提供。

<bean id="poodleClinic" class="example.PoodleClinic">
<qualifier type="example.SpecializedClinic">
<attribute key="species" value="dog"/>
<attribute key="breed" value="poodle"/>
</qualifier>
</bean> 

目前為止,關(guān)于autowire的描述都只是針對(duì)單獨(dú)的實(shí)例,其實(shí)也支持集合。在任何需要得到所有context中某種特定類型的Spring管理對(duì)象的時(shí)候,只需要簡(jiǎn)單地在一個(gè)強(qiáng)類型(strongly-typed)集合上加注@Autowired 注解。

@Autowired
private List<Clinic> allClinics; 

本章節(jié)最后一個(gè)值得指出的特性是自動(dòng)裝配的使用替代了Spring的Aware接口。在Spring2.5之前,如果某個(gè)對(duì)象需要一個(gè)Spring context的ResourceLoader的引用,它可以通過實(shí)現(xiàn)ResourceLoaderAware的方式使得Spring通過setResourceLoader(ResourceLoader resourceLoader)方法來(lái)提供該依賴。借助同樣的方法可以得到Spring管理的MessageSource的引用,甚至可以得到ApplicationContext本身。對(duì)于Spring2.5用戶而言,這個(gè)行為現(xiàn)在通過autowiring得到全面支持(需要指出的是包含這些Spring特定依賴的時(shí)候應(yīng)該考慮周到,特別是它們只能用于從業(yè)務(wù)邏輯清楚地分割出來(lái)的基礎(chǔ)構(gòu)架代碼中)。

@Autowired
private MessageSource messageSource;

@Autowired
private ResourceLoader resourceLoader;

@Autowired
private ApplicationContext applicationContext;

自動(dòng)偵測(cè)Spring組件

從2.0版本開始,Spring引入了構(gòu)造型(stereotype)注解的概念以及將@Repository注解作為數(shù)據(jù)訪問代碼的標(biāo)記的方法。在此基礎(chǔ)上,Spring2.5又加入了兩個(gè)新的注解 —— @Service@Controller 來(lái)完成為通常的三層架構(gòu)(數(shù)據(jù)訪問對(duì)象、服務(wù)、web控制器)角色委任。Spring2.5也引入了泛型@Component注解,其他構(gòu)造型可從邏輯上對(duì)其進(jìn)行擴(kuò)展。通過清晰地指明應(yīng)用程序的角色,這些構(gòu)造型方便了Spring AOP和post-processor的使用,這些post-processor給基于這些角色的加了注解的對(duì)象提供了附加行為。比如,Spring2.0引入了PersistenceExceptionTranslationPostProcessor對(duì)任何帶有@Repository 注解的對(duì)象自動(dòng)激活其數(shù)據(jù)訪問異常轉(zhuǎn)換。

這些注解同樣可以結(jié)合Spring2.5其他一些新性能來(lái)使用:自動(dòng)偵測(cè)classpath上的組件。盡管XML已經(jīng)成為最常見的Spring元數(shù)據(jù)的格式,但它決不是唯一選擇。實(shí)際上,Spring容器內(nèi)的元數(shù)據(jù)是由純Java來(lái)表示的,當(dāng)XML被用來(lái)定義Spring管理對(duì)象時(shí),在實(shí)例化過程之前,那些定義會(huì)被解析并轉(zhuǎn)化成Java對(duì)象。Spring2.5的一個(gè)巨大的新功能是支持從源碼層注解讀取元數(shù)據(jù)。因而,上文描述的自動(dòng)裝配機(jī)制使用注解的元數(shù)據(jù)來(lái)注入依賴,但它仍然需要注冊(cè)至少一個(gè)bean定義以便提供每個(gè)Spring管理對(duì)象的實(shí)現(xiàn)類。組件掃描功能則使得這個(gè)XML中最起碼的bean定義都不再存在需求性。

正如上面所示,Spring注解驅(qū)動(dòng)的自動(dòng)裝配可以在不犧牲細(xì)粒度控制的前提下極大程度地減少XML的使用。組件偵測(cè)機(jī)制將這個(gè)優(yōu)點(diǎn)更發(fā)揚(yáng)光大。全面替代XML中的配置不再必要,組件掃描反而可以處理XML元數(shù)據(jù)來(lái)簡(jiǎn)化整體配置。結(jié)合XML和注解驅(qū)動(dòng)技術(shù)可以得到一個(gè)平衡優(yōu)化的方法,這在2.5版本的PetClinic范例中有詳細(xì)闡述。在該范例中,基礎(chǔ)構(gòu)架組件(數(shù)據(jù)源、事務(wù)管理等)結(jié)合上文提到的外化屬性在XML中定義。數(shù)據(jù)訪問層對(duì)象也有部分在XML中定義,它們的配置也都利用了@Autowired注解來(lái)簡(jiǎn)化依賴注入。最后,web層控制器完全不在XML中顯式定義,相反,下面提供的這段配置被用來(lái)觸發(fā)所有web控制器的自動(dòng)偵測(cè):

<context:component-scan base-package="org.springframework.samples.petclinic.web"/>

需要注意到的是這段示例中使用到了base-package屬性。組件掃描的默認(rèn)匹配規(guī)則會(huì)遞歸偵測(cè)該包(多個(gè)包可以以逗號(hào)分隔的list方式提供)內(nèi)的所有類的所有Spring構(gòu)造型注解。正因?yàn)槿绱?,PetClinic應(yīng)用程序范例中的各類控制器的實(shí)現(xiàn)都采用了@Controller注解(Spring的內(nèi)置構(gòu)造型之一)。請(qǐng)看下面這個(gè)例子:

@Controller
public class ClinicController {

private final Clinic clinic;

@Autowired
public ClinicController(Clinic clinic) {
this.clinic = clinic;
}

 

自動(dòng)偵測(cè)組件在Spring容器中注冊(cè),就像它們?cè)赬ML中被定義一樣。如上所示,那些對(duì)象可以輪流利用注解驅(qū)動(dòng)的自動(dòng)裝配。

組件掃描的匹配規(guī)則可以通過過濾器(filter)來(lái)自定義,以根據(jù)類型、AspectJ表達(dá)式、或針對(duì)命名模式的正則表達(dá)式來(lái)決定包含或不包含哪些組件。默認(rèn)的構(gòu)造型也可以被禁用。比如這里有一個(gè)配置的例子,這個(gè)配置會(huì)忽略默認(rèn)的構(gòu)造型,但會(huì)自動(dòng)偵測(cè)名字以Stub打頭或者包含@Mock注解的所有類:

<context:component-scan base-package="example" use-default-filters="false">
<context:include-filter type="aspectj" expression="example..Stub*"/>
<context:include-filter type="annotation" expression="example.Mock"/>
</context:component-scan> 

類型匹配的限制性也可以用排他的過濾器控制。例如,除了@Repository注解外其他都依賴于默認(rèn)過濾器,那么就需要加入一個(gè)排他過濾器(exclude-filter)。

<context:component-scan base-package="example">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan> 

很明顯,有很多方法可以擴(kuò)展組件掃描來(lái)注冊(cè)自定義的類型。構(gòu)造型注解是最簡(jiǎn)單的選擇,所以構(gòu)造型概念本身也是可擴(kuò)展的。像先前提到的,@Component泛型模型,@Repository、@Service,和@Controller注解都從該構(gòu)造型邏輯擴(kuò)展而得。正因?yàn)槿绱耍?strong>@Component可被用來(lái)作為元注解(也就是說(shuō),在另外的注解上聲明的注解),所有具有@Component元注解的自定義注解都會(huì)被默認(rèn)掃描匹配規(guī)則自動(dòng)偵測(cè)到。一個(gè)例子就有希望讓你領(lǐng)會(huì)到其實(shí)它根本沒有聽起來(lái)那么難。

讓我們回想一下在講@PostConstruct@PreDestroy生命周期注解的時(shí)候的假想的后臺(tái)任務(wù)。也許一個(gè)應(yīng)用程序有很多很多這樣的后臺(tái)任務(wù),這些任務(wù)實(shí)例需要XML bean定義以便在Spring context里注冊(cè)并使它們自己的生命周期方法在正確時(shí)候被調(diào)用。利用組件掃描就不再需要這些顯式的XML bean定義。如果這些后臺(tái)任務(wù)都實(shí)現(xiàn)一個(gè)相同的接口或者都沿用同樣的命名慣例,那么可以用include-filters。然而,更簡(jiǎn)單的方法是為這些任務(wù)對(duì)象創(chuàng)建一個(gè)注解并提供@Component元注解。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface BackgroundTask {
String value() 
default "";
}
 

然后在所有后臺(tái)任務(wù)的類定義中提供自定義構(gòu)造型注解。

@BackgroundTask
public class FilePoller {

@PostConstruct
public void startPolling() {

}


@PreDestroy
public void stopPolling() {

}


}
 

泛型@Component注解可以像例子中提供的那樣簡(jiǎn)單使用,自定義注解技術(shù)則提供了一個(gè)使用更具涵義的、領(lǐng)域特定的名字的機(jī)會(huì)。這些領(lǐng)域特定注解提供更深入的機(jī)會(huì),比如使用AspectJ切點(diǎn)表達(dá)式來(lái)識(shí)別所有后臺(tái)任務(wù),以便增加advice來(lái)監(jiān)控這些任務(wù)的活動(dòng)性。

默認(rèn)的,組件被偵測(cè)到的時(shí)候,Spring會(huì)自動(dòng)生成一個(gè)沒有修飾符的類名作為bean名字。上一個(gè)例子中,生成的bean名字會(huì)是filePoller。但是,任何加注了Spring構(gòu)造型注解(@Component、@Repository、@Service@Controller)或是加注了其他的以@Component作為元注解的注解(比如上面例子中的@BackgroundTask )的類,構(gòu)造型注解的value屬性可以被顯式指定,實(shí)例將該值作為它的bean名字注冊(cè)到context中。接下來(lái)的例子里,實(shí)例名應(yīng)該是petClinic而不是默認(rèn)生成的名字simpleJdbcClinic。

@Service("petClinic")
public class SimpleJdbcClinic {

}
 

同樣的,在下面修正版的FilePoller例子里,生成的bean名字應(yīng)該是poller而不是filePoller。

@BackgroundTask("poller")
public class FilePoller {

}
 

雖然所有Spring管理對(duì)象都被默認(rèn)地當(dāng)作單例實(shí)例來(lái)處理,但有些時(shí)候還是有必要為某個(gè)對(duì)象指明一個(gè)備用的范圍(scope)。舉個(gè)例子來(lái)說(shuō),在web層,一個(gè)Spring管理對(duì)象可能捆綁到request或session的范圍。對(duì)于2.0版本,Spring的scope機(jī)制更具延展性,這樣一來(lái),自定義scope可以被注冊(cè)到應(yīng)用程序上下文(application context)。在XML配置中,僅僅是簡(jiǎn)單地包含進(jìn)scope屬性及該scope的名字就可以了。

<bean id="shoppingCart" class="example.ShoppingCart" scope="session">

</bean> 

Spring2.5中,為被掃描的組件提供@Scope注解可以起到同樣的作用。

@Component
@Scope(
"session")
public class ShoppingCart {

}
 

這里要指出的最后一點(diǎn)是使用組件掃描時(shí)qualifier注解應(yīng)用是多么的簡(jiǎn)單。在上一節(jié),下面這個(gè)對(duì)象曾被作為使用自定義qualifier注解進(jìn)行自動(dòng)裝配的例子:

@VetSpecialty("dentistry")
private Clinic dentistryClinic; 

同樣的例子接著展現(xiàn)了在XML內(nèi)使用‘qualifier’元素為依賴提供指定目標(biāo)bean定義。在使用組件掃描時(shí),XML元數(shù)據(jù)不是必須的。但自定義修飾符也許在目標(biāo)類定義中被作為類型層注解而引入。另一個(gè)將被掃描的@Repository實(shí)例作為依賴的例子如下:

@Repository
@VetSpecialty(
"dentistry")
public class DentistryClinic implements Clinic {

}
 

最終,因?yàn)榍懊娴睦诱宫F(xiàn)了自定義注解及其屬性的例子,相等同的非XML表示依賴目標(biāo)的方法如下:

@Repository
@SpecializedClinic(species
="dog", breed="poodle")
public class PoodleClinic implements Clinic {

}
 

小結(jié)

Spring2.5在很多方面都提供了很有意義的新功能。本文主要關(guān)注于怎樣通過掌控Java注解的力量將配置簡(jiǎn)化。就如在JSR-250中定義的那樣,Spring支持公共注解(Common Annotations),同時(shí)為自動(dòng)裝配過程的更細(xì)粒度的控制提供了額外注解。Spring2.5也擴(kuò)展了從Spring2.0的@Repository就開始的構(gòu)造型(stereotype)注解,并且所有這些構(gòu)造型注解都可以和新的組件掃描功能結(jié)合使用。Spring2.5仍然全面支持基于XML的配置,同時(shí)它又引進(jìn)了一個(gè)新的context命名空間對(duì)常見配置場(chǎng)景提供更精要的文法。實(shí)際上,支持XML和基于注解配置的無(wú)縫結(jié)合最終產(chǎn)生一個(gè)更為平衡的全面的方法?;緲?gòu)架的復(fù)雜配置可以在模塊XML文件中定義,而應(yīng)用程序棧日益增多地更高層配置可以更多的從基于注解的技術(shù)中獲益——前提是都在同一個(gè)Spring2.5應(yīng)用程序context內(nèi)。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
主題:Spring注解入門
Spring 2.5 注解 知識(shí)點(diǎn) - jackpk的專欄 - CSDN博客
Java開發(fā)框架之Spring JDBC
Spring IOC 常用注解
Spring Annotation 詳解
Spring依賴注入:注解注入總結(jié)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服