Scheduled/JmsListenerAnnotationBeanPostProcessor avoids needless re-scanning of non-annotated classes
Issue: SPR-12189
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user