使用SPANN方式将Spring&Quartz与自定义注释集成

在上一篇文章中 ,我们演示了如何在Spring容器中创建和配置带批注的Quartz作业。 我们使用了一个类级别的注释将一些元数据添加到实现Quartz Job的bean中。 批注定义了作业的名称,组及其cron表达式。 后来,大部分代码专用于处理该批注:查找Bean,读取批注,创建JobDetailCronTrigger ,应用它们的属性并将它们传递给调度程序。

如果您正在从事中等规模的大型Spring项目,那么您可能很快就会开始看到样板配置和代码,可以通过将其封装在批注中来进行重构; @QuartzJob注释是一个很好的例子。

masetta中,我们尝试使用Polyforms项目使用注释来实现DAO方法(该方法通常由围绕JPA查询的一些样板代码组成)。 很快,我们发现它并没有像我们所需要的那样可配置和可扩展,在处理命名查询参数和初始化顺序问题方面存在问题(因为Polyforms如何使用方面来实现抽象方法)。 此外,我们使用了自定义注释并“手动”处理了它们,但是它们的数量太多了……

我们想到的span 。 Spann是spring框架的开源扩展,它允许使用注释对spring bean进行高级配置。 为了窥探spann的功能之一,我将依靠我们之前的文章并实现类似的功能。 我将使用spann而不是编码。 如您所见,实现非常简短。

总览

该代码使用Spring的本地Quartz调度实现(如spring参考中所述 )。 Spring的MethodInvokingJobDetailFactoryBean用于创建JobDetail bean,它将作业执行委托给另一个bean的方法。 作为触发器,我使用spring的CronTrigger实现。

为了创建和配置JobDetailCronTrigger 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填充的值设置targetObjecttargetMethod属性。

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时,默认属性值将被忽略。 例如, 时区 ,所述CronTriggerBeanmisfireInstructionNametriggerListenerNames属性将仅在相应的注解的属性值集合; 默认值将被静默忽略。

使用references属性,将jobDetail属性设置为在步骤1中创建的bean:s​​pann将查找附加到具有“ quartzJob ”角色的带注释方法的bean。

请注意, timeZone注释属性类型为String ,而CronTriggerBeantimeZone属性的类型为TimeZone 。 该值由Spring本地处理,使用Spring的PropertyEditor工具透明地转换为TimeZone 。 您甚至可以使用Spring的$ {…}语法进行表达式替换。

签入的代码包含用于创建间隔触发器的第三个注释,此示例稍后将使用它。

3.配置spann和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的其他注释一样灵活,在某些用例中它们没有涵盖范围。 但是spann的低级API允许从头开始创建新的注释,从而为开发人员提供了对bean定义的创建和配置的精细控制。 您甚至可以通过实现自己的MetadataVisitor来使用spann处理任何其他类元数据 ,可以选择全部忽略注释。

参考: Spring&Quartz与自定义注释的集成,这是我们W4G合作伙伴 Ron Piterman的SPANN方法

相关文章 :


翻译自: https://www.javacodegeeks.com/2011/10/spring-quartz-integration-with-custom_31.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值