[SPRING] TaskScheduler, @Scheduled 및 석영
SPRINGTaskScheduler, @Scheduled 및 석영
기본 스케쥴러로 @Scheduled를 석영으로 만드는 방법이 있습니까?
내가 생각할 수있는 두 가지,하지만 둘 다 몇 가지 작업이 필요합니다.
질문 : 위의 두 가지 옵션에 대해 이미 작성된 것이 있고 또 다른 옵션이 있습니까?
해결법
-
==============================
1.나는 내 자신의 봄 석영 "다리"를 만들었습니다. 나는 봄에 대한 개선으로 제안 할 계획이다.
나는 내 자신의 봄 석영 "다리"를 만들었습니다. 나는 봄에 대한 개선으로 제안 할 계획이다.
먼저 quartz Job 인터페이스를 구현하는 클래스에 배치 할 새로운 주석을 작성했다.
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Component @Scope("prototype") public @interface ScheduledJob { String cronExpression() default ""; long fixedRate() default -1; boolean durable() default false; boolean shouldRecover() default true; String name() default ""; String group() default ""; }
(프로토 타입 범위 - 쿼츠는 각 인스턴스의 실행이 새로운 인스턴스라고 가정합니다. 저는 쿼츠 전문가가 아니므로 기대에 부합했습니다. 중복 된 경우 @Scope 주석을 제거하면됩니다)
그런 다음 컨텍스트가 새로 고쳐지거나 시작될 때마다 @ScheduledJob으로 주석 처리 된 모든 클래스를 찾아 쿼츠 스케줄러에 등록 할 때 ApplicationListener를 정의했습니다.
/** * This class listeners to ContextStartedEvent, and when the context is started * gets all bean definitions, looks for the @ScheduledJob annotation, * and registers quartz jobs based on that. * * Note that a new instance of the quartz job class is created on each execution, * so the bean has to be of "prototype" scope. Therefore an applicationListener is used * rather than a bean postprocessor (unlike singleton beans, prototype beans don't get * created on application startup) * * @author bozho * */ public class QuartzScheduledJobRegistrar implements EmbeddedValueResolverAware, ApplicationContextAware, ApplicationListener<ContextRefreshedEvent> { private Scheduler scheduler; private StringValueResolver embeddedValueResolver; private Map<JobListener, String> jobListeners; private ApplicationContext applicationContext; public void setEmbeddedValueResolver(StringValueResolver resolver) { this.embeddedValueResolver = resolver; } public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @SuppressWarnings("unchecked") @Override public void onApplicationEvent(ContextRefreshedEvent event) { if (event.getApplicationContext() == this.applicationContext) { try { scheduler.clear(); for (Map.Entry<JobListener, String> entry : jobListeners.entrySet()) { scheduler.getListenerManager().addJobListener(entry.getKey(), NameMatcher.nameStartsWith(entry.getValue())); } } catch (SchedulerException ex) { throw new IllegalStateException(ex); } DefaultListableBeanFactory factory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory(); String[] definitionNames = factory.getBeanDefinitionNames(); for (String definitionName : definitionNames) { BeanDefinition definition = factory.getBeanDefinition(definitionName); try { if (definition.getBeanClassName() != null) { Class<?> beanClass = Class.forName(definition.getBeanClassName()); registerJob(beanClass); } } catch (ClassNotFoundException e) { throw new IllegalArgumentException(e); } } } } public void registerJob(Class<?> targetClass) { ScheduledJob annotation = targetClass.getAnnotation(ScheduledJob.class); if (annotation != null) { Assert.isTrue(Job.class.isAssignableFrom(targetClass), "Only classes implementing the quartz Job interface can be annotated with @ScheduledJob"); @SuppressWarnings("unchecked") // checked on the previous line Class<? extends Job> jobClass = (Class<? extends Job>) targetClass; JobDetail jobDetail = JobBuilder.newJob() .ofType(jobClass) .withIdentity( annotation.name().isEmpty() ? targetClass.getSimpleName() : annotation.name(), annotation.group().isEmpty() ? targetClass.getPackage().getName() : annotation.group()) .storeDurably(annotation.durable()) .requestRecovery(annotation.shouldRecover()) .build(); TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger() .withIdentity(jobDetail.getKey().getName() + "_trigger", jobDetail.getKey().getGroup() + "_triggers") .startNow(); String cronExpression = annotation.cronExpression(); long fixedRate = annotation.fixedRate(); if (!BooleanUtils.xor(new boolean[] {!cronExpression.isEmpty(), fixedRate >=0})) { throw new IllegalStateException("Exactly one of 'cronExpression', 'fixedRate' is required. Offending class " + targetClass.getName()); } if (!cronExpression.isEmpty()) { if (embeddedValueResolver != null) { cronExpression = embeddedValueResolver.resolveStringValue(cronExpression); } try { triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)); } catch (ParseException e) { throw new IllegalArgumentException(e); } } if (fixedRate >= 0) { triggerBuilder.withSchedule( SimpleScheduleBuilder.simpleSchedule() .withIntervalInMilliseconds(fixedRate) .repeatForever()) .withIdentity(jobDetail.getKey().getName() + "_trigger", jobDetail.getKey().getGroup() + "_triggers"); } try { scheduler.scheduleJob(jobDetail, triggerBuilder.build()); } catch (SchedulerException e) { throw new IllegalStateException(e); } } } public void setScheduler(Scheduler scheduler) { this.scheduler = scheduler; } public void setJobListeners(Map<JobListener, String> jobListeners) { this.jobListeners = jobListeners; } }
그런 다음 커스텀 JobFactory를 사용하여 석영을 플러그인하여 봄 컨텍스트로 작업을 생성해야했습니다.
public class QuartzSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware { private SchedulerContext schedulerContext; private ApplicationContext ctx; @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { Job job = ctx.getBean(bundle.getJobDetail().getJobClass()); BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(job); MutablePropertyValues pvs = new MutablePropertyValues(); pvs.addPropertyValues(bundle.getJobDetail().getJobDataMap()); pvs.addPropertyValues(bundle.getTrigger().getJobDataMap()); if (this.schedulerContext != null) { pvs.addPropertyValues(this.schedulerContext); } bw.setPropertyValues(pvs, true); return job; } public void setSchedulerContext(SchedulerContext schedulerContext) { this.schedulerContext = schedulerContext; super.setSchedulerContext(schedulerContext); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.ctx = applicationContext; } }
마지막으로, xml 설정 :
<bean id="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="jobFactory"> <bean class="com.foo.bar.scheduling.QuartzSpringBeanJobFactory" /> </property> </bean> <bean id="scheduledJobRegistrar" class="com.foo.bar.scheduling.QuartzScheduledJobRegistrar"> <property name="scheduler" ref="quartzScheduler" /> <property name="jobListeners"> <map> <entry value=""> <!-- empty string = match all jobs --> <key><bean class="com.foo.bar.scheduling.FailuresJobListener"/></key> </entry> </map> </property> </bean>
-
==============================
2.준비된 구현이없는 것처럼 보입니다. 그러나, 당신 자신의 배선은 매우 어렵지 않아야합니다 :
준비된 구현이없는 것처럼 보입니다. 그러나, 당신 자신의 배선은 매우 어렵지 않아야합니다 :
@Service public class QuartzTaskScheduler implements TaskScheduler { //... }
Spring이 그것을 사용하게 만들기 :
<task:annotation-driven/> <bean class="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor"> <property name="scheduler" ref="quartzTaskScheduler"/> </bean>
이 경로를 따라 간다면 스프링 프레임 워크 (org.springframework.scheduling.quartz 패키지)에 코드를 제공하거나 최소한 그 문제를 열어 볼 수있다.
from https://stackoverflow.com/questions/6788811/taskscheduler-scheduled-and-quartz by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] RestTemplate을 사용한 Spring 4.0.0 기본 인증 (0) | 2019.01.29 |
---|---|
[SPRING] 스프링 테스트에서 @Test 메소드를 사용하기 전에 데이터베이스를 한 번만 채우는 방법은 무엇입니까? (0) | 2019.01.29 |
[SPRING] 스프링 부트 시작 시간 최소화 [duplicate] (0) | 2019.01.29 |
[SPRING] Spring에서 트랜잭션을 사용할 때 포스트 커밋 만들기 (0) | 2019.01.29 |
[SPRING] 클래스 패스에있는 jar 파일 안에있는 스프링 애플리케이션 컨텍스트 파일로드하기 (0) | 2019.01.29 |