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 3fbca70456f..0a08f615e5f 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 @@ -327,7 +327,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 { 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 317da9d64b9..de23de51921 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; @@ -96,10 +97,10 @@ public class JmsListenerAnnotationBeanPostProcessor protected final Log logger = LogFactory.getLog(getClass()); - private JmsListenerEndpointRegistry endpointRegistry; - private String containerFactoryBeanName = DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME; + private JmsListenerEndpointRegistry endpointRegistry; + private final MessageHandlerMethodFactoryAdapter messageHandlerMethodFactory = new MessageHandlerMethodFactoryAdapter(); @@ -120,14 +121,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. @@ -136,6 +129,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. @@ -179,6 +180,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) { @@ -189,9 +194,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(); @@ -215,8 +217,13 @@ 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); + if (bean instanceof AopInfrastructureBean) { + // Ignore AOP infrastructure such as scoped proxies. + return bean; + } + + Class targetClass = AopProxyUtils.ultimateTargetClass(bean); + if (!this.nonAnnotatedClasses.contains(targetClass)) { Map> annotatedMethods = MethodIntrospector.selectMethods(targetClass, new MethodIntrospector.MetadataLookup>() { @Override @@ -227,9 +234,9 @@ public class JmsListenerAnnotationBeanPostProcessor } }); 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 { 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 46a8f9fedcc..cda57a98d07 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,6 +39,7 @@ import org.springframework.jms.config.JmsListenerEndpointRegistry; import org.springframework.jms.config.MessageListenerTestContainer; import org.springframework.jms.config.MethodJmsListenerEndpoint; import org.springframework.jms.listener.SimpleMessageListenerContainer; +import org.springframework.messaging.handler.annotation.Header; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.stereotype.Component; import org.springframework.transaction.PlatformTransactionManager; @@ -73,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); @@ -98,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 { @@ -108,9 +113,9 @@ public class JmsListenerAnnotationBeanPostProcessorTests { } @Test - public void sendToAnnotationFoundOnProxy() throws Exception { + public void sendToAnnotationFoundOnInterfaceProxy() throws Exception { ConfigurableApplicationContext context = new AnnotationConfigApplicationContext( - Config.class, ProxyConfig.class, ProxyTestBean.class); + Config.class, ProxyConfig.class, InterfaceProxyTestBean.class); try { JmsListenerContainerTestFactory factory = context.getBean(JmsListenerContainerTestFactory.class); assertEquals("one container should have been registered", 1, factory.getListenerContainers().size()); @@ -120,12 +125,42 @@ public class JmsListenerAnnotationBeanPostProcessorTests { MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint; assertTrue(AopUtils.isJdkDynamicProxy(methodEndpoint.getBean())); assertTrue(methodEndpoint.getBean() instanceof SimpleService); - assertEquals(SimpleService.class.getMethod("handleIt", String.class), methodEndpoint.getMethod()); - assertEquals(ProxyTestBean.class.getMethod("handleIt", String.class), methodEndpoint.getMostSpecificMethod()); + 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 { + context.close(); + } + } + + @Test + public void sendToAnnotationFoundOnCglibProxy() throws Exception { + ConfigurableApplicationContext context = new AnnotationConfigApplicationContext( + Config.class, ProxyConfig.class, ClassProxyTestBean.class); + try { + JmsListenerContainerTestFactory factory = context.getBean(JmsListenerContainerTestFactory.class); + assertEquals("one container should have been registered", 1, factory.getListenerContainers().size()); - Method m = ReflectionUtils.findMethod(endpoint.getClass(), "getDefaultResponseDestination"); - ReflectionUtils.makeAccessible(m); - Object destination = ReflectionUtils.invokeMethod(m, endpoint); + JmsListenerEndpoint endpoint = factory.getListenerContainers().get(0).getEndpoint(); + assertEquals("Wrong endpoint type", MethodJmsListenerEndpoint.class, endpoint.getClass()); + 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 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 { @@ -174,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; } @@ -204,18 +239,29 @@ public class JmsListenerAnnotationBeanPostProcessorTests { interface SimpleService { - void handleIt(String body); + void handleIt(String value, String body); } @Component - static class ProxyTestBean implements SimpleService { + static class InterfaceProxyTestBean implements SimpleService { @Override @Transactional @JmsListener(destination = "testQueue") @SendTo("foobar") - public void handleIt(String body) { + public void handleIt(@Header String value, String body) { + } + } + + + @Component + static class ClassProxyTestBean { + + @Transactional + @JmsListener(destination = "testQueue") + @SendTo("foobar") + public void handleIt(@Header String value, String body) { } } @@ -224,7 +270,7 @@ public class JmsListenerAnnotationBeanPostProcessorTests { static class InvalidProxyTestBean implements SimpleService { @Override - public void handleIt(String body) { + public void handleIt(String value, String body) { } @Transactional