Cảm ơn cả hai câu trả lời của bạn, bạn đã cung cấp thông tin giá trị đã đưa tôi đến giải pháp này, vì vậy tôi đã bỏ phiếu cho cả hai câu trả lời.
Tôi đã chọn tạo bộ xử lý bài đăng tùy chỉnh và chú thích tùy chỉnh @Scheduled
.
Mã đơn giản (về cơ bản nó là một sự thích nghi tầm thường của mã Spring hiện có) và tôi thực sự tự hỏi tại sao họ không làm điều đó như thế này từ khi bắt đầu. Số lượng mã của BeanPostProcessor
được tăng gấp đôi kể từ khi tôi chọn xử lý chú thích cũ và chú thích mới.
Nếu bạn có bất kỳ đề xuất nào về cách cải thiện mã này, tôi sẽ rất vui khi biết điều đó.
CustomScheduled lớp (chú thích)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CustomScheduled {
String cron() default "";
String fixedDelay() default "";
String fixedRate() default "";
}
CustomScheduledAnnotationBeanPostProcessor lớp
public class CustomScheduledAnnotationBeanPostProcessor implements BeanPostProcessor, Ordered, EmbeddedValueResolverAware, ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, DisposableBean
{
private static final Logger LOG = LoggerFactory.getLogger(CustomScheduledAnnotationBeanPostProcessor.class);
// omitted code is the same as in ScheduledAnnotationBeanPostProcessor......
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
// processes both @Scheduled and @CustomScheduled annotations
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
final Class<?> targetClass = AopUtils.getTargetClass(bean);
ReflectionUtils.doWithMethods(targetClass, new MethodCallback() {
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
Scheduled oldScheduledAnnotation = AnnotationUtils.getAnnotation(method, Scheduled.class);
if (oldScheduledAnnotation != null) {
LOG.info("@Scheduled found at method {}", method.getName());
Assert.isTrue(void.class.equals(method.getReturnType()), "Only void-returning methods may be annotated with @Scheduled.");
Assert.isTrue(method.getParameterTypes().length == 0, "Only no-arg methods may be annotated with @Scheduled.");
if (AopUtils.isJdkDynamicProxy(bean)) {
try {
// found a @Scheduled method on the target class for this JDK proxy -> is it
// also present on the proxy itself?
method = bean.getClass().getMethod(method.getName(), method.getParameterTypes());
} catch (SecurityException ex) {
ReflectionUtils.handleReflectionException(ex);
} catch (NoSuchMethodException ex) {
throw new IllegalStateException(String.format(
"@Scheduled method '%s' found on bean target class '%s', " +
"but not found in any interface(s) for bean JDK proxy. Either " +
"pull the method up to an interface or switch to subclass (CGLIB) " +
"proxies by setting proxy-target-class/proxyTargetClass " +
"attribute to 'true'", method.getName(), targetClass.getSimpleName()));
}
}
Runnable runnable = new ScheduledMethodRunnable(bean, method);
boolean processedSchedule = false;
String errorMessage = "Exactly one of 'cron', 'fixedDelay', or 'fixedRate' is required.";
String cron = oldScheduledAnnotation.cron();
if (!"".equals(cron)) {
processedSchedule = true;
if (embeddedValueResolver != null) {
cron = embeddedValueResolver.resolveStringValue(cron);
}
cronTasks.put(runnable, cron);
}
long fixedDelay = oldScheduledAnnotation.fixedDelay();
if (fixedDelay >= 0) {
Assert.isTrue(!processedSchedule, errorMessage);
processedSchedule = true;
fixedDelayTasks.put(runnable, fixedDelay);
}
long fixedRate = oldScheduledAnnotation.fixedRate();
if (fixedRate >= 0) {
Assert.isTrue(!processedSchedule, errorMessage);
processedSchedule = true;
fixedRateTasks.put(runnable, fixedRate);
}
Assert.isTrue(processedSchedule, errorMessage);
}
CustomScheduled newScheduledAnnotation = AnnotationUtils.getAnnotation(method, CustomScheduled.class);
if (newScheduledAnnotation != null) {
LOG.info("@CustomScheduled found at method {}", method.getName());
Assert.isTrue(void.class.equals(method.getReturnType()), "Only void-returning methods may be annotated with @CustomScheduled.");
Assert.isTrue(method.getParameterTypes().length == 0, "Only no-arg methods may be annotated with @CustomScheduled.");
if (AopUtils.isJdkDynamicProxy(bean)) {
try {
// found a @CustomScheduled method on the target class for this JDK proxy -> is it
// also present on the proxy itself?
method = bean.getClass().getMethod(method.getName(), method.getParameterTypes());
} catch (SecurityException ex) {
ReflectionUtils.handleReflectionException(ex);
} catch (NoSuchMethodException ex) {
throw new IllegalStateException(String.format("@CustomScheduled method '%s' found on bean target class '%s', "
+ "but not found in any interface(s) for bean JDK proxy. Either "
+ "pull the method up to an interface or switch to subclass (CGLIB) "
+ "proxies by setting proxy-target-class/proxyTargetClass " + "attribute to 'true'", method.getName(),
targetClass.getSimpleName()));
}
}
Runnable runnable = new ScheduledMethodRunnable(bean, method);
boolean processedSchedule = false;
String errorMessage = "Exactly one of 'cron', 'fixedDelay', or 'fixedRate' is required.";
boolean numberFormatException = false;
String numberFormatErrorMessage = "Delay value is not a number!";
String cron = newScheduledAnnotation.cron();
if (!"".equals(cron)) {
processedSchedule = true;
if (embeddedValueResolver != null) {
cron = embeddedValueResolver.resolveStringValue(cron);
}
cronTasks.put(runnable, cron);
LOG.info("Put cron in tasks map with value {}", cron);
}
// fixedDelay value resolving
Long fixedDelay = null;
String resolverDelayCandidate = newScheduledAnnotation.fixedDelay();
if (!"".equals(resolverDelayCandidate)) {
try {
if (embeddedValueResolver != null) {
resolverDelayCandidate = embeddedValueResolver.resolveStringValue(resolverDelayCandidate);
fixedDelay = Long.valueOf(resolverDelayCandidate);
} else {
fixedDelay = Long.valueOf(newScheduledAnnotation.fixedDelay());
}
} catch (NumberFormatException e) {
numberFormatException = true;
}
}
Assert.isTrue(!numberFormatException, numberFormatErrorMessage);
if (fixedDelay != null && fixedDelay >= 0) {
Assert.isTrue(!processedSchedule, errorMessage);
processedSchedule = true;
fixedDelayTasks.put(runnable, fixedDelay);
LOG.info("Put fixedDelay in tasks map with value {}", fixedDelay);
}
// fixedRate value resolving
Long fixedRate = null;
String resolverRateCandidate = newScheduledAnnotation.fixedRate();
if (!"".equals(resolverRateCandidate)) {
try {
if (embeddedValueResolver != null) {
fixedRate = Long.valueOf(embeddedValueResolver.resolveStringValue(resolverRateCandidate));
} else {
fixedRate = Long.valueOf(newScheduledAnnotation.fixedRate());
}
} catch (NumberFormatException e) {
numberFormatException = true;
}
}
Assert.isTrue(!numberFormatException, numberFormatErrorMessage);
if (fixedRate != null && fixedRate >= 0) {
Assert.isTrue(!processedSchedule, errorMessage);
processedSchedule = true;
fixedRateTasks.put(runnable, fixedRate);
LOG.info("Put fixedRate in tasks map with value {}", fixedRate);
}
Assert.isTrue(processedSchedule, errorMessage);
}
}
});
return bean;
}
}
mùa xuân-context.xml tập tin cấu hình
<beans...>
<!-- Enables the use of a @CustomScheduled annotation-->
<bean class="org.package.CustomScheduledAnnotationBeanPostProcessor" />
</beans>
liên quan: http://stackoverflow.com/questions/6788811/taskscheduler-scheduled-and-quartz/6840970#6840970 – Bozho