Spring2.5新特性

来源:互联网 发布:外卖智能调度算法 编辑:程序博客网 时间:2024/06/11 16:19

生之初,Spring框架就守它的宗旨:化企业级应用开,同时给杂问题提供大的、非侵入性解决方案。一年前布的Spring2.0就把些主推到了一个新的高度。XML Schema的支持和自定命名空的使用大大减少了基于XML的配置。使用Java5及更新版本java的开如今可以利用植入了像泛型generic)和注解等新言特性的Spring。最近,和AspectJ表达式言的密集成,使得以非侵入方式添加跨越定良好的Spring管理象分的行可能。

布的Spring2.5继续坚持了向,特那些使用Java 5或更新版本java的开提供了一步化而大的新特性。些新特性包括:注解驱动的依性注入(annotation-driven dependency injection),使用注解而非XML元数据来自动侦测classpath上的Spring件,注解命周期方法的支持,一个新的web控制器模型将求映射到加注解的方法上,在测试框架中支持Junit4Spring XML命名空的新增内容,等等。

本文是探讨这些新特性的3篇系列文章中的第一篇。本文将主要关注于化的配置和在Spring用程序上下文(application context)核心新增的基于注解的功能;第二篇文章将涵盖web可用的新特性;最后一篇文章将着重介集成和测试的新增性能。一系列的三篇文章中引用的例子都基于Spring PetClinic用程序范例。此范例最近被重构以用于展示Spring最新功能,并被包含于Spring 2.5布下包中,可以从Spring Framework "samples/petclinic"下的"readme.txt"文件可以得知关于如何构建和部署PetClinic用程序,掌握本文提到的新技的最佳方法也就是PetClinic用程序中所展示的特性试验

Spring支持JSR-250注解

Java EE5中引入了“Java平台的公共注解(Common Annotations for the Java Platform,而且公共注解从Java SE 6一开始就被包含其中。 20065月,BEA宣布了他在一个名Pitchfork目上与Interface21合作该项目提供了基于SpringJava EE 5程模型的实现,包括支持用于注入(injection)、截( interception)和事务处理(transactions)的JSR-250注解和EJB 3注解(JSR-220) 2.5版本中,Spring框架的核心(core在支持以下JSR-250注解:

·            @Resource

·            @PostConstruct

·            @PreDestroy

Spring些注解在任何开发环境下都可以使用——是否有用程序服——甚至是集成测试环境都可以。激活这样的支持仅仅是注册一个独的Spring post-processor的事情:

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

@Resource注解

@Resource 注解被用来激活一个命名源(named resource)的依注入,在JavaEE用程序中,注解被典型地转换为绑定于JNDI context中的一个象。 Spring支持使用@ResourceJNDI lookup来解析象,默地,有与@Resource注解所提供名字相匹配的“bean namebean名字)Spring管理象会被注入。 在下面的例子中,Spring会向加了注解的setter方法传递beandataSourceSpring管理象的引用。

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

直接使用@Resource注解一个域(field)同是可能的。不暴露setter方法,代发紧凑并且提供了域不可修改的外益正如下面将要明的,@Resource注解甚至不需要一个式的字符串,在没有提供任何的情况下,域名将被当作默认值

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

方式被用到setter方法的候,默名是从相的属性衍生出来,话说,命名'setDataSource'的方法被用来理名'dataSource'的属性。

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

@Resource没有式提供名字的候,如果根据默名字找不到对应Spring管理象,注入机制会回型匹配(type-match)。如果好只有一个Spring管理象符合型,那么它会被注入。通过设CommonAnnotationBeanPostProcessor ‘fallbackToDefaultTypeMatch’属性“false”(默认值“true”)可以禁用一特性。

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

正如上文所提到的,在解析@Resource注解的依赖时Spring支持JNDI-lookup。如若要所有使用@Resource注解的依赖进JNDI lookup,那也只要将CommonAnnotationBeanPostProcessor'alwaysUseJndiLookup' 标识设true就可以了(默认值false)。

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

另一个选择是,激活指定‘resource-ref-mappings’的依据全局JNDI名的找,在@Resource注解内提供mappedName’属性。即使目标对实际上是一个JNDI源,仍然推荐引入一个Spring管理象,这样可以提供一个并且因此降低耦合程度。自Spring2.0开始添加命名空以来,定一个委托SpringJNDI lookupbean得愈发简练

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

个方法的点在于层带来了巨大的部署性。比如,一个独的系统测试环应该不再需要JNDI注册。在种情况下,在系统测试配置中可以提供如下的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}"/>

便提一下,上面的例子中,实际JDBC接属性从一个属性文件(properties file)解析而来,在个属性文件里,关字与提供的${占位符}互相对应需要注册一个名PropertyPlaceholderConfigurerBeanFactoryPostProcessor实现来完成。是具体化那些属性(通常是针对特定境的属性)常用的技些属性可能比其他配置修改得更为频繁。

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

Srping2.5中新加入了‘context’命名空个命名空间让得到更为简洁的方式来实现属性占位符(property placeholder)的配置:

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

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

@PostConstruct @PreDestroy注解分用来触Spring的初始化和销毁个特性在原有基上得到了展,但并没有替代在Spring2.5之前版本中提供的同的回的另两个选项。第一个选项实现SpringInitializingBean DisposableBean 接口中的一个或两个。两个接口都需要一个回方法的实现(afterPropertiesSet()destroy() )种基于接口的方法利用了Spring动识别任何实现这些接口的Spring管理象的能力,因而不再需要另外的配置。另一方面,Spring的一个关是尽可能的非侵入。因此,Spring并不采用实现这Spring特定接口的方法,而利用第二个选项,那就是提供他自己的初始化和销毁方法。尽管入侵性小,但缺点在于使用个方式的就必须显式声明bean元素的init-methoddestroy-method属性。式配置有是必的,例如当回需要在开控制能力之外的代上被用的候。PetClinic用程序很好地明了景。当它和JDBC配置一起运行的候,会用到一个第三方DataSource,并且它式声明了一个destroy-method。另外要注意到的是,独的接池数据源是dataSource的另一个部署选项,并且不需要修改任何代

<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程中,如果一个象需要用一个初始化的回方法的个回方法可以采用@PostConstruct来注解。例如一个假想的例子,一个后台任需要在启候就开始一个文件目录进轮询

public class FilePoller {
 
   @PostConstruct
  
public void startPolling() {
         ...
   }
   ...
}

似地,一个在Spring管理象上用@PreDestroy注解的方法会在象寄宿的用程序上下文(application context)关候被用。

public class FilePoller {
 
   @PreDestroy
  
public void stopPolling() {
         ...
   }
  
...
}

在添加了JSR-250注解的支持以后,在的Spring2.5合前面提到的两种生命周期方法的长处。将@PostConstruct@PreDestroy方法注解加入,足可以实现在受Spring管理的上下文(context)中触话说,不需要另外基于XML的配置。同两个注解是Java言本身的一部分(甚至被包括在Java SE 版本6中),所以无需引入特定Spring包。两个注解有在其他境中也能理解的标识语义点,随着时间的推移,Java可能会发现这些注解在第三方开发库中被越来越多的运用到。最后,基于注解生命周期回的其中一个有趣的果是,不止一个方法可以两个注解中的任何一个,并且所有注解了的方法会被用。

激活刚刚描述的关于@Resource @PostConstruct@PreDestroy注解的所有行,正如上文提到的,需要SpringCommonAnnotationBeanPostProcessor提供一个bean但另一个更简练的方法可能是使用2.5中的新的context命名空

<context:annotation-config/>
 

引入个元素将不单单注册一个CommonAnnotationBeanPostProcessor,也会像下文将叙述的那激活自装配(autowire)行CommonAnnotationBeanPostProcessor@WebServiceRef @EJB注解提供支持。些将在本文系列的第三篇中和Spring2.5集成提供的其他新特性一起讨论

利用注解来粒度自装配

涵盖Spring装配支持的文档中常常会提到由于自装配机制的粗粒度而伴随有很多限制性。Spring2.5之前,自装配可以通很多不同的方式来配置:构造器,setter,名字setter,或者自动侦测(在方式中Spring选择装配一个构造器或者setter)。些不同的选择提供了很大程度的灵活性,但它中没有一个方法能提供粒度控制。话说Spring2.5之前不可能自装配某个setter方法的特定子集,或者通过类型或名字来自装配它的一些属性。果,Spring到将自装配用到构建原型和测试中的好,但当提到在品中维护和支持系统时,大部分人认为,加入冗式配置于澄清它所担职责是非常得的。

然而,Spring2.5大幅度地改了布局。如上文所述,自配置选项现在已展,支持JSR-250 @Resource注解来激活在每个方法或域基上被命名源的自装配。然而,@Resource注解若独使用的有很多限制。因此,Sring2.5了一个名@Autowired的注解一步提高控制级别激活里所的行需要注册一个独的bean

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

另外如上文提到的,context命名空提供了一个更明的方法。它将激活本文所讨论的两个post-processorAutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor)和我Spring2.0中引入的基于注解的post-processorRequiredAnnotationBeanPostProcessorPersistenceAnnotationBeanPostProcessor

<context:annotation-config/>
 

利用@Autowired 注解可以应类型注入依。域、构造器和方法都可以激活此行实际上,aotowired方法并不一定要是setter方法,且可以接受多个参数。下面个例子是完整的可接受的用法:

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

地,@Autowired注解的依认为是必的。然而,也可以将required属性值设false来声明它中的任何一个。在下面个例子中,DefaultStrategy只有在context命名空中没有SomeStrategy型的Spring管理才能被使用。

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

过类行的自装配明地在Spring context包含多于一个期望型的象的候造成歧。默地,如果一个必的依没不是恰好一个bean与之对应,自装配机制就会失。同的,于任何一个可属性,如果它有一个以上的候,也都会失(如果属性可且没有任何候可用的属性会被简单地跳)。有很多不同的配置选项可以避免些冲突。

Context有一个指定型的一个主关例,对这型定bean义应该包含‘primary’属性。当Context中含有其他可用例的个方法就很适用,但那些非主关键实式配置的。

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

在需要更多控制的候,任何autowired的域、构造参数、或者方法参数可以一步加注@Qualifier注解。qualifier可以包含一个字符串,在种情况下,Spring试图名字来找到对应象。

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

@Qualifier一个独立注解存在的主要原因是它可以被用在构造器参数或方法参数上,但上文提到的@Autowired注解只能运用在构造器或方法本身。

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

上,@Qualifier一个独的注解在定制化方面提供了更多的好。用自定的注解在自装配程中也可以起到qualifier的作用,最简单实现方式是在运用自定注解的同@Qualifier它的元注解。

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

自定注解可以选择包含一个来提供通名字匹配的功能,但更普遍的用法是将它作标记注解或定一个qualifier程提供一些更多含。例如,下面个摘录则了一个域,它应该和通名字匹配得到的果中合格的行自装配。

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

在使用XML配置来达到依解析的目标时'qualifier' 子元素可以被加注到bean中。在下文的描部分,我将呈一个可供选择的非XML方法。

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

了避免@Qualifier注解的任何依性,可以在Spring context中提供一个CustomAutowireConfigurerbean并直接注册所有自定注解型:

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

在,自定符被式声明了,就不再需要@Qualifier个元注解符了。

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

,在配置AutowiredAnnotationBeanPostProcessor候,取代@Autowired注解都是有可能的。

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

大部分情况下,定自定标记注解的能力合通名字或其他文法值进行匹配选项,足以完成自装配程的粒度控制。Spring支持在qualifier注解上任意数目的任意属性。比如,下面是一个极为细粒度修的例子。

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

自定符的实现应该义这些属性:

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

自定属性可以匹配那些XMLbeanqualifier注解的属性子元素。些元素通常以值对方式提供。

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

目前止,关于autowire的描述都只是针对单独的例,其也支持集合。在任何需要得到所有context中某种特定型的Spring管理象的候,只需要简单地在一个强类型(strongly-typed)集合上加注@Autowired 注解。

@Autowired
private List<Clinic> allClinics;

本章最后一个得指出的特性是自装配的使用替代了SpringAware接口。在Spring2.5之前,如果某个象需要一个Spring contextResourceLoader的引用,它可以通过实现ResourceLoaderAware的方式使得SpringsetResourceLoader(ResourceLoader resourceLoader)方法来提供。借助同的方法可以得到Spring管理的MessageSource的引用,甚至可以得到ApplicationContext本身。Spring2.5而言,个行为现在通autowiring得到全面支持(需要指出的是包含Spring特定依应该周到,特是它只能用于从业务逻辑清楚地分割出来的基构架代中)。

@Autowired
private MessageSource messageSource;
 
@Autowired
private ResourceLoader resourceLoader;
 
@Autowired
private ApplicationContext applicationContext;
 

动侦测Spring

2.0版本开始,Spring引入了构造型(stereotype)注解的概念以及将@Repository注解作数据访问标记的方法。在此基上,Spring2.5又加入了两个新的注解 —— @Service@Controller 来完成通常的三架构(数据访问对象、服web控制器)角色委任。Spring2.5也引入了泛型@Component注解,其他构造型可从逻辑展。通清晰地指明用程序的角色,些构造型方便了Spring AOPpost-processor的使用,post-processor基于些角色的加了注解的象提供了附加行。比如,Spring2.0引入了PersistenceExceptionTranslationPostProcessor任何@Repository 注解的象自激活其数据访问异常转换

些注解同可以Spring2.5其他一些新性能来使用:自动侦测classpath上的件。尽XML最常Spring元数据的格式,但它决不是唯一选择实际上,Spring容器内的元数据是由Java来表示的,当XML被用来定Spring管理,在例化程之前,那些定会被解析并化成Java象。Spring2.5的一个巨大的新功能是支持从源码层注解取元数据。因而,上文描述的自装配机制使用注解的元数据来注入依,但它仍然需要注册至少一个bean以便提供每个Spring管理象的实现类描功能使得XML中最起bean都不再存在需求性。

正如上面所示,Spring注解驱动的自装配可以在不粒度控制的前提下极大程度地减少XML的使用。侦测机制将点更发扬光大。全面替代XML中的配置不再必要,描反而可以XML元数据来化整体配置。XML和注解驱动可以得到一个平衡化的方法,2.5版本的PetClinic范例中有详细阐述。在范例中,基构架件(数据源、事管理等)合上文提到的外化属性在XML中定。数据访问层对象也有部分在XML中定,它的配置也都利用了@Autowired注解来化依注入。最后,web控制器完全不XML式定,相反,下面提供的段配置被用来触所有web控制器的自动侦测

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

需要注意到的是段示例中使用到了base-package属性。描的默匹配规则递归侦测该包(多个包可以以逗号分隔的list方式提供)内的所有的所有Spring构造型注解。正因如此,PetClinic用程序范例中的各控制器的实现都采用了@Controller注解(Spring内置构造型之一)。看下面个例子:

@Controller
public class ClinicController {
 
  
private final Clinic clinic;
 
   @Autowired
  
public ClinicController(Clinic clinic) {
         
this.clinic = clinic;
   }
 ...

动侦测组件在Spring容器中注册,就像它XML中被定。如上所示,那些象可以流利用注解驱动的自装配。

描的匹配规则可以通过过滤器(filter)来自定,以根据型、AspectJ表达式、或针对命名模式的正表达式来决定包含或不包含哪些件。默的构造型也可以被禁用。比如里有一个配置的例子,个配置会忽略默的构造型,但会自动侦测名字以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注解外其他都依于默认过滤器,那么就需要加入一个排他过滤(exclude-filter)

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

很明,有很多方法可以描来注册自定型。构造型注解是最简单选择,所以构造型概念本身也是可展的。像先前提到的,@Component泛型模型,@Repository@Service,@Controller注解都从构造型逻辑扩展而得。正因如此,@Component可被用来作元注解(也就是,在另外的注解上声明的注解),所有具有@Component元注解的自定注解都会被默认扫描匹配规则动侦测到。一个例子就有希望会到其它根本没有听起来那么

回想一下在@PostConstruct@PreDestroy生命周期注解的候的假想的后台任一个用程序有很多很多这样的后台任些任务实例需要XML bean以便在Spring context里注册并使它自己的生命周期方法在正确候被用。利用描就不再需要式的XML bean。如果些后台任实现一个相同的接口或者都沿用同的命名例,那么可以用include-filters。然而,更简单的方法是为这些任务对建一个注解并提供@Component元注解。

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

然后在所有后台任中提供自定构造型注解。

@BackgroundTask
public class FilePoller {
 
   @PostConstruct
  
public void startPolling() {
         ...
   }
 
   @PreDestroy
  
public void stopPolling() {
         ...
   }
   ...
}

泛型@Component注解可以像例子中提供的那样简单使用,自定注解技术则提供了一个使用更具涵的、域特定的名字的机会。域特定注解提供更深入的机会,比如使用AspectJ切点表达式来识别所有后台任,以便增加advice些任的活性。

的,件被侦测到的候,Spring会自生成一个没有修符的名作bean名字。上一个例子中,生成的bean名字会是filePoller。但是,任何加注了Spring构造型注解(@Component@Repository@Service @Controller)或是加注了其他的以@Component元注解的注解(比如上面例子中的@BackgroundTask )的,构造型注解的value属性可以被式指定,例将该值它的bean名字注册到context中。接下来的例子里,例名应该petClinic而不是默生成的名字simpleJdbcClinic

@Service("petClinic")
public class SimpleJdbcClinic {
   ...
}

的,在下面修正版的FilePoller例子里,生成的bean名字应该poller而不是filePoller

@BackgroundTask("poller")
 
public class FilePoller {
   ...
}

然所有Spring管理象都被默地当作例来理,但有些是有必要某个象指明一个用的范scope)。个例子来,在web,一个Spring管理象可能捆requestsession的范2.0版本,Springscope机制更具延展性,这样一来,自定scope可以被注册到用程序上下文(application context)。在XML配置中,仅仅简单地包含scope属性及scope的名字就可以了。

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

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

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

里要指出的最后一点是使用qualifier注解用是多么的简单。在上一,下面象曾被作使用自定qualifier注解行自装配的例子:

@VetSpecialty("dentistry")
private Clinic dentistryClinic;

的例子接着展了在XML内使用‘qualifier’元素提供指定目bean。在使用XML元数据不是必的。但自定符也在目标类中被作为类注解而引入。另一个将被描的@Repository例作的例子如下:

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

,因前面的例子展了自定注解及其属性的例子,相等同的非XML表示依的方法如下:

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

Spring2.5在很多方面都提供了很有意的新功能。本文主要关注于怎掌控Java注解的力量将配置化。就如在JSR-250中定的那Spring支持公共注解(Common Annotations),同时为装配程的更粒度的控制提供了外注解。Spring2.5展了从Spring2.0@Repository就开始的构造型(stereotype)注解,并且所有些构造型注解都可以和新的描功能合使用。Spring2.5仍然全面支持基于XML的配置,同它又引了一个新的context命名空间对配置景提供更精要的文法。实际上,支持XML和基于注解配置的无缝结合最终产生一个更平衡的全面的方法。基本构架的复配置可以在模XML文件中定,而用程序日益增多地更高配置可以更多的从基于注解的技——前提是都在同一个Spring2.5用程序context内。

在接下来的文章中,我讨论到在Spring web层强大的基于注解的新功能。敬关注系列的下一篇文章

 

原创粉丝点击