diff --git a/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java b/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java index 5509dd53ab..e5818d6f82 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java @@ -17,11 +17,18 @@ package org.springframework.scheduling.annotation; import java.lang.reflect.Method; +import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.Map; +import java.util.Set; import java.util.TimeZone; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledExecutorService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; @@ -74,6 +81,8 @@ public class ScheduledAnnotationBeanPostProcessor implements BeanPostProcessor, Ordered, EmbeddedValueResolverAware, BeanFactoryAware, SmartInitializingSingleton, DisposableBean { + protected final Log logger = LogFactory.getLog(getClass()); + private Object scheduler; private StringValueResolver embeddedValueResolver; @@ -82,6 +91,9 @@ public class ScheduledAnnotationBeanPostProcessor private final ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar(); + private final Set> nonAnnotatedClasses = + Collections.newSetFromMap(new ConcurrentHashMap, Boolean>(64)); + @Override public int getOrder() { @@ -117,7 +129,9 @@ public class ScheduledAnnotationBeanPostProcessor */ @Deprecated public void setApplicationContext(ApplicationContext applicationContext) { - this.beanFactory = applicationContext; + if (this.beanFactory == null) { + this.beanFactory = applicationContext; + } } @@ -146,12 +160,11 @@ public class ScheduledAnnotationBeanPostProcessor this.registrar.setScheduler(schedulers.values().iterator().next()); } else if (schedulers.size() >= 2){ - throw new IllegalStateException( - "More than one TaskScheduler and/or ScheduledExecutorService " + - "exist within the context. Remove all but one of the beans; or " + - "implement the SchedulingConfigurer interface and call " + - "ScheduledTaskRegistrar#setScheduler explicitly within the " + - "configureTasks() callback. Found the following beans: " + schedulers.keySet()); + throw new IllegalStateException("More than one TaskScheduler and/or ScheduledExecutorService " + + "exist within the context. Remove all but one of the beans; or implement the " + + "SchedulingConfigurer interface and call ScheduledTaskRegistrar#setScheduler " + + "explicitly within the configureTasks() callback. Found the following beans: " + + schedulers.keySet()); } } @@ -166,15 +179,33 @@ public class ScheduledAnnotationBeanPostProcessor @Override public Object postProcessAfterInitialization(final Object bean, String beanName) { - Class targetClass = AopUtils.getTargetClass(bean); - ReflectionUtils.doWithMethods(targetClass, new MethodCallback() { - @Override - public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { - for (Scheduled scheduled : AnnotationUtils.getRepeatableAnnotation(method, Schedules.class, Scheduled.class)) { - processScheduled(scheduled, method, bean); + if (!this.nonAnnotatedClasses.contains(bean.getClass())) { + final Set annotatedMethods = new LinkedHashSet(1); + Class targetClass = AopUtils.getTargetClass(bean); + ReflectionUtils.doWithMethods(targetClass, new MethodCallback() { + @Override + public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { + for (Scheduled scheduled : + AnnotationUtils.getRepeatableAnnotation(method, Schedules.class, Scheduled.class)) { + processScheduled(scheduled, method, bean); + annotatedMethods.add(method); + } + } + }); + if (annotatedMethods.isEmpty()) { + this.nonAnnotatedClasses.add(bean.getClass()); + if (logger.isDebugEnabled()) { + logger.debug("No @Scheduled annotations found on bean class: " + bean.getClass()); } } - }); + else { + // Non-empty set of methods + if (logger.isDebugEnabled()) { + logger.debug(annotatedMethods.size() + " @Scheduled methods processed on bean '" + beanName + + "': " + annotatedMethods); + } + } + } return bean; } diff --git a/spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java b/spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java index 0cc6732381..edf6c97634 100644 --- a/spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java +++ b/spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java @@ -17,9 +17,16 @@ package org.springframework.jms.annotation; import java.lang.reflect.Method; +import java.util.Collections; +import java.util.LinkedHashSet; import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; @@ -81,6 +88,8 @@ public class JmsListenerAnnotationBeanPostProcessor static final String DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME = "jmsListenerContainerFactory"; + protected final Log logger = LogFactory.getLog(getClass()); + private JmsListenerEndpointRegistry endpointRegistry; private String containerFactoryBeanName = DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME; @@ -93,6 +102,9 @@ public class JmsListenerAnnotationBeanPostProcessor private final AtomicInteger counter = new AtomicInteger(); + private final Set> nonAnnotatedClasses = + Collections.newSetFromMap(new ConcurrentHashMap, Boolean>(64)); + @Override public int getOrder() { @@ -181,16 +193,33 @@ public class JmsListenerAnnotationBeanPostProcessor @Override public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException { - Class targetClass = AopUtils.getTargetClass(bean); - ReflectionUtils.doWithMethods(targetClass, new ReflectionUtils.MethodCallback() { - @Override - public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { - JmsListener jmsListener = AnnotationUtils.getAnnotation(method, JmsListener.class); - if (jmsListener != null) { - processJmsListener(jmsListener, method, bean); + if (!this.nonAnnotatedClasses.contains(bean.getClass())) { + final Set annotatedMethods = new LinkedHashSet(1); + Class targetClass = AopUtils.getTargetClass(bean); + ReflectionUtils.doWithMethods(targetClass, new ReflectionUtils.MethodCallback() { + @Override + public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { + JmsListener jmsListener = AnnotationUtils.getAnnotation(method, JmsListener.class); + if (jmsListener != null) { + processJmsListener(jmsListener, method, bean); + annotatedMethods.add(method); + } + } + }); + if (annotatedMethods.isEmpty()) { + this.nonAnnotatedClasses.add(bean.getClass()); + if (logger.isDebugEnabled()) { + logger.debug("No @JmsListener annotations found on bean class: " + bean.getClass()); } } - }); + else { + // Non-empty set of methods + if (logger.isDebugEnabled()) { + logger.debug(annotatedMethods.size() + " @JmsListener methods processed on bean '" + beanName + + "': " + annotatedMethods); + } + } + } return bean; }