如果您正在从事中等规模的大型Spring项目,那么您可能很快就会开始看到样板配置和代码,可以通过将其封装在批注中来进行重构。 @QuartzJob注释是一个很好的例子。
在masetta中,我们尝试使用Polyforms项目使用注释来实现DAO方法(该方法通常由围绕JPA查询的一些样板代码组成)。 很快,我们发现它并没有像我们所需要的那样可配置和可扩展,在处理命名查询参数和初始化顺序问题方面存在问题(因为Polyforms如何使用方面来实现抽象方法)。 此外,我们使用了自定义注释并“手动”处理了它们,但是它们的数量太多了……
我们想到的是span 。 Spann是spring框架的开源扩展,它允许使用注释对spring bean进行高级配置。 为了窥探spann的功能之一,我将依靠我们之前的文章并实现类似的功能。 我将使用spann而不是编码。 如您所见,实现非常简短。
总览
该代码使用Spring的本地Quartz调度实现(如spring参考中所述 )。 Spring的MethodInvokingJobDetailFactoryBean用于创建JobDetail bean,它将作业执行委托给另一个bean的方法。 作为触发器,我使用spring的CronTrigger实现。
为了创建和配置JobDetail和CronTrigger Bean,我将使用spann的@BeanConfig注释创建方法级别的注释。
代码
可以使用以下命令将示例代码作为跨项目的Maven项目检出:
svn co http://spann.googlecode.com/svn/trunk/spann-quartz-example
它包括一个带有所有必需的依赖项坐标的pom和一个功能测试用例。
1.创建注释以配置MethodInvokingJobDetailFactoryBean
package com.masetta.spann.quartzexample.annotations;import java.lang.annotation.*;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import com.masetta.spann.metadata.common.Artifact;
import com.masetta.spann.spring.base.beanconfig.*;
import com.masetta.spann.spring.base.beanconfig.factories.*;@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@BeanConfig(create=MethodInvokingJobDetailFactoryBean.class,attached=@Attached(role="quartzJob",scope=Artifact.METHOD),explicit=true,wire={@WireMeta(property="targetObject",scope=Artifact.CLASS,factory=BeanReferenceFactory.class),@WireMeta(property="targetMethod",scope=Artifact.METHOD,factory=MetadataNameFactory.class)})
public @interface QuartzJob {String name();String group();boolean concurrent() default true;}
该@BeanConfig注释创建和使用QuartzJob的注释的属性( 名称 , 组和并发 )配置一个MethodInvokingJobDetailFactoryBean中 。
已配置的bean通过“ quartzJob ”角色“附加”到带注释的方法。 稍后将使用它来将JobDetail bean注入触发器。 “连接”是内部跨度概念。 它允许通过指定工件(例如类或方法)和语义角色(此处为“ quartzJob”)而不是按名称来引用bean。 这将启用spanning最强大的功能注释合成 ,此处也将进行演示。
wire属性使用给定工厂使用从当前工件的元数据 (在本例中为MethodMetadata ), ScanContext和Annotation填充的值设置targetObject和targetMethod属性。
2.创建一个cron触发器注释
package com.masetta.spann.quartzexample.annotations;import java.lang.annotation.*;
import org.springframework.scheduling.quartz.CronTriggerBean;
import com.masetta.spann.metadata.common.Artifact;
import com.masetta.spann.spring.base.beanconfig.*;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@BeanConfig(create=CronTriggerBean.class,attached=@Attached(role="quartzTrigger",scope=Artifact.METHOD), explicit=true,references=@SpannReference(property="jobDetail",role="quartzJob", scope=Artifact.METHOD)
)
public @interface Cron {String cronExpression();String timeZone() default "";String misfireInstructionName() default "";String[] triggerListenerNames() default {}; }
再次使用@BeanConfig批注,这次创建和配置CronTriggerBean 。
显式属性指示如何处理默认的注释属性值。 当explicit为true时,默认属性值将被忽略。 例如, 时区 ,所述CronTriggerBean的misfireInstructionName和triggerListenerNames属性将仅在相应的注解的属性值集合; 默认值将被静默忽略。
使用references属性,将jobDetail属性设置为在步骤1中创建的bean:spann将查找附加到具有“ quartzJob ”角色的带注释方法的bean。
请注意, timeZone注释属性类型为String ,而CronTriggerBean的timeZone属性的类型为TimeZone 。 该值由Spring本地处理,使用Spring的PropertyEditor工具透明地转换为TimeZone 。 您甚至可以使用Spring的$ {…}语法进行表达式替换。
签入的代码包含用于创建间隔触发器的第三个注释,此示例稍后将使用它。
3.配置span和spring的SchedulerFactoryBean
我们的applicationContext.xml非常简短:
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:spann="http://os.masetta.com/spann/schema/spann-1.0"xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://os.masetta.com/spann/schema/spann-1.0 http://os.masetta.com/spann/schema/spann-1.0.xsd"><context:component-scan base-package="com.masetta.spann.quartzexample"/><spann:scan base-package="com.masetta.spann.quartzexample"/><bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire=”byType”/></beans>
如果您知道spring,那么这里就没有什么魔术了:如spring参考中所述,我配置了spring的组件扫描,spann扫描和SchedulerFactoryBean ,仅在这里,我让spring将所有触发bean自动装配到相应的属性,因此autowire ='byType' 。
4.使用注释
package com.masetta.spann.quartzexample.test;import java.util.concurrent.atomic.AtomicInteger;import org.springframework.stereotype.Component;import com.masetta.spann.quartzexample.annotations.*;
import com.masetta.spann.spring.core.annotations.VisitMethods;@Component
@VisitMethods
public class Savana {private AtomicInteger newElemphants = new AtomicInteger();private AtomicInteger newZebras = new AtomicInteger();@QuartzJob(name="zebraBorn",group="savana")@Interval(repeatInterval=200)public void zebraBorn() {newZebras.incrementAndGet();}@QuartzJob(name="elephantBorn",group="savana")@Cron(cronExpression="0/2 * * ? * * *")public void elephantBorn() {newElemphants.incrementAndGet();}public int getNewZebras() {return newZebras.get();}public int getNewElephants() {return newElemphants.get();}}
该bean是通过spring的@Component注释配置的。 它是普通的Spring bean,并且任何Spring或方面注释(@ Autowired , @Resource ,@ Transactional )都将由Spring本地处理。
默认情况下,spann仅处理类级别的注释。 @VisitMethods指示spann也访问此类的方法并处理其注释(如果存在)。
新注释的使用很简单:每个计划的方法都应使用@QuartzJob (创建委托的JobDetail )和@Cron或@Interval注释(此处未显示,但在svn中可用)进行注释。 。
这也演示了spann的批注组合 ,该批注组合使批注可以粒度化和可插入: @QuartzJob可以与配置触发器 bean的任何注释一起使用,而@Cron和@Interval可以与配置JobDetail bean的任何注释一起使用。
摘要
Spann是Spring框架的开源扩展,它允许使用注释进行高级Bean配置。 该代码演示了spann的@BeanConfig批注如何使用批注创建Quartz计划的作业。
该示例使用spann的高级API(即@BeanConfig批注),该API在spann项目本身中实现。 Spann的高级API包括其他允许方法替换(用于在运行时实现抽象方法,内部使用cglib进行实现的方法),合成适配器创建和全面的JPA Query支持的注释。
Spann与spring的集成非常紧密:它创建了“普通的老式spring bean”,就像用XML或@Component批注定义的那样。 这使您可以利用spring的所有bean功能:可以通过spring的ApplicationContext检索bean,具有正常的bean生命周期,可以进行后处理(例如,用于表达式替换),自动装配,使用方面进行拦截,通过JMX管理等等。上。 您不需要黑客和变通办法,也不需要重新实现或复制和调整现有的Spring代码。 此外,您的样板代码更少,样板配置也更少。
与@BeanConfig和spann的其他注释一样灵活,在某些用例中它们没有涉及。 但是Span的低级API允许从头开始创建新的注释,从而为开发人员提供了对bean定义的创建和配置的精细控制。 您甚至可以通过实现自己的MetadataVisitor来使用spann处理任何其他类元数据 ,可以选择全部忽略注释。
参考: Spring&Quartz与Custom Annotation的集成,这是我们W4G合作伙伴 Ron Piterman的SPANN方法 。
相关文章 :
- Spring,Quartz和JavaMail集成教程
- 在运行时交换出Spring Bean配置
- Spring MVC3 Hibernate CRUD示例应用程序
- 使用Spring将POJO公开为JMX MBean
- Java教程和Android教程列表
翻译自: https://www.javacodegeeks.com/2011/10/spring-quartz-integration-with-custom_31.html