Browse Source

Scheduled/JmsListenerAnnotationBeanPostProcessor avoids needless re-scanning of non-annotated classes

Issue: SPR-12189
pull/646/merge
Juergen Hoeller 11 years ago
parent
commit
58b22ceddc
  1. 59
      spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java
  2. 45
      spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java

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

@ -17,11 +17,18 @@
package org.springframework.scheduling.annotation; package org.springframework.scheduling.annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService; 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.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanFactoryAware;
@ -74,6 +81,8 @@ public class ScheduledAnnotationBeanPostProcessor
implements BeanPostProcessor, Ordered, EmbeddedValueResolverAware, BeanFactoryAware, implements BeanPostProcessor, Ordered, EmbeddedValueResolverAware, BeanFactoryAware,
SmartInitializingSingleton, DisposableBean { SmartInitializingSingleton, DisposableBean {
protected final Log logger = LogFactory.getLog(getClass());
private Object scheduler; private Object scheduler;
private StringValueResolver embeddedValueResolver; private StringValueResolver embeddedValueResolver;
@ -82,6 +91,9 @@ public class ScheduledAnnotationBeanPostProcessor
private final ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar(); private final ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar();
private final Set<Class<?>> nonAnnotatedClasses =
Collections.newSetFromMap(new ConcurrentHashMap<Class<?>, Boolean>(64));
@Override @Override
public int getOrder() { public int getOrder() {
@ -117,7 +129,9 @@ public class ScheduledAnnotationBeanPostProcessor
*/ */
@Deprecated @Deprecated
public void setApplicationContext(ApplicationContext applicationContext) { 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()); this.registrar.setScheduler(schedulers.values().iterator().next());
} }
else if (schedulers.size() >= 2){ else if (schedulers.size() >= 2){
throw new IllegalStateException( throw new IllegalStateException("More than one TaskScheduler and/or ScheduledExecutorService " +
"More than one TaskScheduler and/or ScheduledExecutorService " + "exist within the context. Remove all but one of the beans; or implement the " +
"exist within the context. Remove all but one of the beans; or " + "SchedulingConfigurer interface and call ScheduledTaskRegistrar#setScheduler " +
"implement the SchedulingConfigurer interface and call " + "explicitly within the configureTasks() callback. Found the following beans: " +
"ScheduledTaskRegistrar#setScheduler explicitly within the " + schedulers.keySet());
"configureTasks() callback. Found the following beans: " + schedulers.keySet());
} }
} }
@ -166,15 +179,33 @@ public class ScheduledAnnotationBeanPostProcessor
@Override @Override
public Object postProcessAfterInitialization(final Object bean, String beanName) { public Object postProcessAfterInitialization(final Object bean, String beanName) {
Class<?> targetClass = AopUtils.getTargetClass(bean); if (!this.nonAnnotatedClasses.contains(bean.getClass())) {
ReflectionUtils.doWithMethods(targetClass, new MethodCallback() { final Set<Method> annotatedMethods = new LinkedHashSet<Method>(1);
@Override Class<?> targetClass = AopUtils.getTargetClass(bean);
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { ReflectionUtils.doWithMethods(targetClass, new MethodCallback() {
for (Scheduled scheduled : AnnotationUtils.getRepeatableAnnotation(method, Schedules.class, Scheduled.class)) { @Override
processScheduled(scheduled, method, bean); 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; return bean;
} }

45
spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java

@ -17,9 +17,16 @@
package org.springframework.jms.annotation; package org.springframework.jms.annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger; 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.aop.support.AopUtils;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
@ -81,6 +88,8 @@ public class JmsListenerAnnotationBeanPostProcessor
static final String DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME = "jmsListenerContainerFactory"; static final String DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME = "jmsListenerContainerFactory";
protected final Log logger = LogFactory.getLog(getClass());
private JmsListenerEndpointRegistry endpointRegistry; private JmsListenerEndpointRegistry endpointRegistry;
private String containerFactoryBeanName = DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME; 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 AtomicInteger counter = new AtomicInteger();
private final Set<Class<?>> nonAnnotatedClasses =
Collections.newSetFromMap(new ConcurrentHashMap<Class<?>, Boolean>(64));
@Override @Override
public int getOrder() { public int getOrder() {
@ -181,16 +193,33 @@ public class JmsListenerAnnotationBeanPostProcessor
@Override @Override
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException { public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
Class<?> targetClass = AopUtils.getTargetClass(bean); if (!this.nonAnnotatedClasses.contains(bean.getClass())) {
ReflectionUtils.doWithMethods(targetClass, new ReflectionUtils.MethodCallback() { final Set<Method> annotatedMethods = new LinkedHashSet<Method>(1);
@Override Class<?> targetClass = AopUtils.getTargetClass(bean);
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { ReflectionUtils.doWithMethods(targetClass, new ReflectionUtils.MethodCallback() {
JmsListener jmsListener = AnnotationUtils.getAnnotation(method, JmsListener.class); @Override
if (jmsListener != null) { public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
processJmsListener(jmsListener, method, bean); 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; return bean;
} }

Loading…
Cancel
Save