From c4a7567a5e031cf5e2f58394ff9f01dd6083dc7b Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sun, 12 Aug 2018 11:47:28 +0200 Subject: [PATCH] Post-processors consistently ignore ScopedObject/AopInfrastructureBean JmsListenerAnnotationBeanPostProcessor also ignores JmsListenerContainerFactory and JmsListenerEndpointRegistry, avoiding unnecessary annotation introspection on framework classes. Issue: SPR-17166 Issue: SPR-16933 --- .../ScheduledAnnotationBeanPostProcessor.java | 6 +-- ...msListenerAnnotationBeanPostProcessor.java | 47 +++++++++++-------- ...tenerAnnotationBeanPostProcessorTests.java | 42 ++++++++++------- 3 files changed, 54 insertions(+), 41 deletions(-) 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 b4789513d9..2a0218b60b 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 @@ -350,7 +350,7 @@ public class ScheduledAnnotationBeanPostProcessor if (annotatedMethods.isEmpty()) { this.nonAnnotatedClasses.add(targetClass); if (logger.isTraceEnabled()) { - logger.trace("No @Scheduled annotations found on bean class: " + bean.getClass()); + logger.trace("No @Scheduled annotations found on bean class: " + targetClass); } } else { @@ -507,9 +507,7 @@ public class ScheduledAnnotationBeanPostProcessor * @see ScheduledMethodRunnable#ScheduledMethodRunnable(Object, Method) */ protected Runnable createRunnable(Object target, Method method) { - Assert.isTrue(method.getParameterCount() == 0, - "Only no-arg methods may be annotated with @Scheduled"); - + Assert.isTrue(method.getParameterCount() == 0, "Only no-arg methods may be annotated with @Scheduled"); Method invocableMethod = AopUtils.selectInvocableMethod(method, target.getClass()); return new ScheduledMethodRunnable(target, invocableMethod); } 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 533799bb77..9fc1a4db37 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 @@ -28,6 +28,7 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.aop.framework.AopInfrastructureBean; import org.springframework.aop.framework.AopProxyUtils; import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; @@ -98,10 +99,10 @@ public class JmsListenerAnnotationBeanPostProcessor protected final Log logger = LogFactory.getLog(getClass()); @Nullable - private JmsListenerEndpointRegistry endpointRegistry; + private String containerFactoryBeanName = DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME; @Nullable - private String containerFactoryBeanName = DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME; + private JmsListenerEndpointRegistry endpointRegistry; private final MessageHandlerMethodFactoryAdapter messageHandlerMethodFactory = new MessageHandlerMethodFactoryAdapter(); @@ -124,14 +125,6 @@ public class JmsListenerAnnotationBeanPostProcessor return LOWEST_PRECEDENCE; } - /** - * Set the {@link JmsListenerEndpointRegistry} that will hold the created - * endpoint and manage the lifecycle of the related listener container. - */ - public void setEndpointRegistry(JmsListenerEndpointRegistry endpointRegistry) { - this.endpointRegistry = endpointRegistry; - } - /** * Set the name of the {@link JmsListenerContainerFactory} to use by default. *

If none is specified, "jmsListenerContainerFactory" is assumed to be defined. @@ -140,6 +133,14 @@ public class JmsListenerAnnotationBeanPostProcessor this.containerFactoryBeanName = containerFactoryBeanName; } + /** + * Set the {@link JmsListenerEndpointRegistry} that will hold the created + * endpoint and manage the lifecycle of the related listener container. + */ + public void setEndpointRegistry(JmsListenerEndpointRegistry endpointRegistry) { + this.endpointRegistry = endpointRegistry; + } + /** * Set the {@link MessageHandlerMethodFactory} to use to configure the message * listener responsible to serve an endpoint detected by this processor. @@ -183,6 +184,10 @@ public class JmsListenerAnnotationBeanPostProcessor } } + if (this.containerFactoryBeanName != null) { + this.registrar.setContainerFactoryBeanName(this.containerFactoryBeanName); + } + if (this.registrar.getEndpointRegistry() == null) { // Determine JmsListenerEndpointRegistry bean from the BeanFactory if (this.endpointRegistry == null) { @@ -193,9 +198,6 @@ public class JmsListenerAnnotationBeanPostProcessor this.registrar.setEndpointRegistry(this.endpointRegistry); } - if (this.containerFactoryBeanName != null) { - this.registrar.setContainerFactoryBeanName(this.containerFactoryBeanName); - } // Set the custom handler method factory once resolved by the configurer MessageHandlerMethodFactory handlerMethodFactory = this.registrar.getMessageHandlerMethodFactory(); @@ -218,9 +220,15 @@ public class JmsListenerAnnotationBeanPostProcessor } @Override - public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException { - if (!this.nonAnnotatedClasses.contains(bean.getClass())) { - Class targetClass = AopProxyUtils.ultimateTargetClass(bean); + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (bean instanceof AopInfrastructureBean || bean instanceof JmsListenerContainerFactory || + bean instanceof JmsListenerEndpointRegistry) { + // Ignore AOP infrastructure such as scoped proxies. + return bean; + } + + Class targetClass = AopProxyUtils.ultimateTargetClass(bean); + if (!this.nonAnnotatedClasses.contains(targetClass)) { Map> annotatedMethods = MethodIntrospector.selectMethods(targetClass, (MethodIntrospector.MetadataLookup>) method -> { Set listenerMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations( @@ -228,16 +236,15 @@ public class JmsListenerAnnotationBeanPostProcessor return (!listenerMethods.isEmpty() ? listenerMethods : null); }); if (annotatedMethods.isEmpty()) { - this.nonAnnotatedClasses.add(bean.getClass()); + this.nonAnnotatedClasses.add(targetClass); if (logger.isTraceEnabled()) { - logger.trace("No @JmsListener annotations found on bean type: " + bean.getClass()); + logger.trace("No @JmsListener annotations found on bean type: " + targetClass); } } else { // Non-empty set of methods annotatedMethods.forEach((method, listeners) -> - listeners.forEach(listener -> - processJmsListener(listener, method, bean))); + listeners.forEach(listener -> processJmsListener(listener, method, bean))); if (logger.isDebugEnabled()) { logger.debug(annotatedMethods.size() + " @JmsListener methods processed on bean '" + beanName + "': " + annotatedMethods); diff --git a/spring-jms/src/test/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessorTests.java b/spring-jms/src/test/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessorTests.java index 90ff30d307..cda57a98d0 100644 --- a/spring-jms/src/test/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessorTests.java +++ b/spring-jms/src/test/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessorTests.java @@ -74,8 +74,10 @@ public class JmsListenerAnnotationBeanPostProcessorTests { assertEquals("Wrong endpoint type", MethodJmsListenerEndpoint.class, endpoint.getClass()); MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint; assertEquals(SimpleMessageListenerTestBean.class, methodEndpoint.getBean().getClass()); - assertEquals(SimpleMessageListenerTestBean.class.getMethod("handleIt", String.class), methodEndpoint.getMethod()); - assertEquals(SimpleMessageListenerTestBean.class.getMethod("handleIt", String.class), methodEndpoint.getMostSpecificMethod()); + assertEquals(SimpleMessageListenerTestBean.class.getMethod("handleIt", String.class), + methodEndpoint.getMethod()); + assertEquals(SimpleMessageListenerTestBean.class.getMethod("handleIt", String.class), + methodEndpoint.getMostSpecificMethod()); SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer(); methodEndpoint.setupListenerContainer(listenerContainer); @@ -99,8 +101,10 @@ public class JmsListenerAnnotationBeanPostProcessorTests { assertEquals("Wrong endpoint type", MethodJmsListenerEndpoint.class, endpoint.getClass()); MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint; assertEquals(MetaAnnotationTestBean.class, methodEndpoint.getBean().getClass()); - assertEquals(MetaAnnotationTestBean.class.getMethod("handleIt", String.class), methodEndpoint.getMethod()); - assertEquals(MetaAnnotationTestBean.class.getMethod("handleIt", String.class), methodEndpoint.getMostSpecificMethod()); + assertEquals(MetaAnnotationTestBean.class.getMethod("handleIt", String.class), + methodEndpoint.getMethod()); + assertEquals(MetaAnnotationTestBean.class.getMethod("handleIt", String.class), + methodEndpoint.getMostSpecificMethod()); assertEquals("metaTestQueue", ((AbstractJmsListenerEndpoint) endpoint).getDestination()); } finally { @@ -121,12 +125,14 @@ public class JmsListenerAnnotationBeanPostProcessorTests { MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint; assertTrue(AopUtils.isJdkDynamicProxy(methodEndpoint.getBean())); assertTrue(methodEndpoint.getBean() instanceof SimpleService); - assertEquals(SimpleService.class.getMethod("handleIt", String.class, String.class), methodEndpoint.getMethod()); - assertEquals(InterfaceProxyTestBean.class.getMethod("handleIt", String.class, String.class), methodEndpoint.getMostSpecificMethod()); - - Method m = ReflectionUtils.findMethod(endpoint.getClass(), "getDefaultResponseDestination"); - ReflectionUtils.makeAccessible(m); - Object destination = ReflectionUtils.invokeMethod(m, endpoint); + assertEquals(SimpleService.class.getMethod("handleIt", String.class, String.class), + methodEndpoint.getMethod()); + assertEquals(InterfaceProxyTestBean.class.getMethod("handleIt", String.class, String.class), + methodEndpoint.getMostSpecificMethod()); + + Method method = ReflectionUtils.findMethod(endpoint.getClass(), "getDefaultResponseDestination"); + ReflectionUtils.makeAccessible(method); + Object destination = ReflectionUtils.invokeMethod(method, endpoint); assertEquals("SendTo annotation not found on proxy", "foobar", destination); } finally { @@ -147,12 +153,14 @@ public class JmsListenerAnnotationBeanPostProcessorTests { MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint; assertTrue(AopUtils.isCglibProxy(methodEndpoint.getBean())); assertTrue(methodEndpoint.getBean() instanceof ClassProxyTestBean); - assertEquals(ClassProxyTestBean.class.getMethod("handleIt", String.class, String.class), methodEndpoint.getMethod()); - assertEquals(ClassProxyTestBean.class.getMethod("handleIt", String.class, String.class), methodEndpoint.getMostSpecificMethod()); - - Method m = ReflectionUtils.findMethod(endpoint.getClass(), "getDefaultResponseDestination"); - ReflectionUtils.makeAccessible(m); - Object destination = ReflectionUtils.invokeMethod(m, endpoint); + assertEquals(ClassProxyTestBean.class.getMethod("handleIt", String.class, String.class), + methodEndpoint.getMethod()); + assertEquals(ClassProxyTestBean.class.getMethod("handleIt", String.class, String.class), + methodEndpoint.getMostSpecificMethod()); + + Method method = ReflectionUtils.findMethod(endpoint.getClass(), "getDefaultResponseDestination"); + ReflectionUtils.makeAccessible(method); + Object destination = ReflectionUtils.invokeMethod(method, endpoint); assertEquals("SendTo annotation not found on proxy", "foobar", destination); } finally { @@ -201,8 +209,8 @@ public class JmsListenerAnnotationBeanPostProcessorTests { @Bean public JmsListenerAnnotationBeanPostProcessor postProcessor() { JmsListenerAnnotationBeanPostProcessor postProcessor = new JmsListenerAnnotationBeanPostProcessor(); - postProcessor.setEndpointRegistry(jmsListenerEndpointRegistry()); postProcessor.setContainerFactoryBeanName("testFactory"); + postProcessor.setEndpointRegistry(jmsListenerEndpointRegistry()); return postProcessor; }