如果您正在從事中等規模的大型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:s??pann將查找附加到具有“ quartzJob ”角色的帶注釋方法的bean。
請注意, timeZone注釋屬性類型為String ,而CronTriggerBean的timeZone屬性的類型為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方法 。
相關文章 :
- 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