Skip to content

Commit d2e8b7e

Browse files
committed
ScheduledAnnotationBeanPostProcessor avoids needless re-scanning of non-annotated classes
Issue: SPR-12189 (cherry picked from commit 58b22ce)
1 parent 7d55715 commit d2e8b7e

File tree

1 file changed

+27
-13
lines changed

1 file changed

+27
-13
lines changed

spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java

+27-13
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@
1717
package org.springframework.scheduling.annotation;
1818

1919
import java.lang.reflect.Method;
20+
import java.util.Collections;
2021
import java.util.HashMap;
22+
import java.util.LinkedHashSet;
2123
import java.util.Map;
24+
import java.util.Set;
2225
import java.util.TimeZone;
26+
import java.util.concurrent.ConcurrentHashMap;
2327
import java.util.concurrent.ScheduledExecutorService;
2428

2529
import org.springframework.aop.support.AopUtils;
@@ -81,6 +85,9 @@ public class ScheduledAnnotationBeanPostProcessor
8185

8286
private final ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar();
8387

88+
private final Set<Class<?>> nonAnnotatedClasses =
89+
Collections.newSetFromMap(new ConcurrentHashMap<Class<?>, Boolean>(64));
90+
8491

8592
@Override
8693
public int getOrder() {
@@ -134,12 +141,11 @@ else if (schedulers.size() == 1) {
134141
this.registrar.setScheduler(schedulers.values().iterator().next());
135142
}
136143
else if (schedulers.size() >= 2){
137-
throw new IllegalStateException(
138-
"More than one TaskScheduler and/or ScheduledExecutorService " +
139-
"exist within the context. Remove all but one of the beans; or " +
140-
"implement the SchedulingConfigurer interface and call " +
141-
"ScheduledTaskRegistrar#setScheduler explicitly within the " +
142-
"configureTasks() callback. Found the following beans: " + schedulers.keySet());
144+
throw new IllegalStateException("More than one TaskScheduler and/or ScheduledExecutorService " +
145+
"exist within the context. Remove all but one of the beans; or implement the " +
146+
"SchedulingConfigurer interface and call ScheduledTaskRegistrar#setScheduler " +
147+
"explicitly within the configureTasks() callback. Found the following beans: " +
148+
schedulers.keySet());
143149
}
144150
}
145151

@@ -154,15 +160,23 @@ public Object postProcessBeforeInitialization(Object bean, String beanName) {
154160

155161
@Override
156162
public Object postProcessAfterInitialization(final Object bean, String beanName) {
157-
Class<?> targetClass = AopUtils.getTargetClass(bean);
158-
ReflectionUtils.doWithMethods(targetClass, new MethodCallback() {
159-
@Override
160-
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
161-
for (Scheduled scheduled : AnnotationUtils.getRepeatableAnnotation(method, Schedules.class, Scheduled.class)) {
162-
processScheduled(scheduled, method, bean);
163+
if (!this.nonAnnotatedClasses.contains(bean.getClass())) {
164+
final Set<Method> annotatedMethods = new LinkedHashSet<Method>(1);
165+
Class<?> targetClass = AopUtils.getTargetClass(bean);
166+
ReflectionUtils.doWithMethods(targetClass, new MethodCallback() {
167+
@Override
168+
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
169+
for (Scheduled scheduled :
170+
AnnotationUtils.getRepeatableAnnotation(method, Schedules.class, Scheduled.class)) {
171+
processScheduled(scheduled, method, bean);
172+
annotatedMethods.add(method);
173+
}
163174
}
175+
});
176+
if (annotatedMethods.isEmpty()) {
177+
this.nonAnnotatedClasses.add(bean.getClass());
164178
}
165-
});
179+
}
166180
return bean;
167181
}
168182

0 commit comments

Comments
 (0)