Browse Source

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
pull/1925/head
Juergen Hoeller 6 years ago
parent
commit
c4a7567a5e
  1. 6
      spring-context/src/main/java/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java
  2. 47
      spring-jms/src/main/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessor.java
  3. 42
      spring-jms/src/test/java/org/springframework/jms/annotation/JmsListenerAnnotationBeanPostProcessorTests.java

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

@ -350,7 +350,7 @@ public class ScheduledAnnotationBeanPostProcessor
if (annotatedMethods.isEmpty()) { if (annotatedMethods.isEmpty()) {
this.nonAnnotatedClasses.add(targetClass); this.nonAnnotatedClasses.add(targetClass);
if (logger.isTraceEnabled()) { 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 { else {
@ -507,9 +507,7 @@ public class ScheduledAnnotationBeanPostProcessor
* @see ScheduledMethodRunnable#ScheduledMethodRunnable(Object, Method) * @see ScheduledMethodRunnable#ScheduledMethodRunnable(Object, Method)
*/ */
protected Runnable createRunnable(Object target, Method method) { protected Runnable createRunnable(Object target, Method method) {
Assert.isTrue(method.getParameterCount() == 0, Assert.isTrue(method.getParameterCount() == 0, "Only no-arg methods may be annotated with @Scheduled");
"Only no-arg methods may be annotated with @Scheduled");
Method invocableMethod = AopUtils.selectInvocableMethod(method, target.getClass()); Method invocableMethod = AopUtils.selectInvocableMethod(method, target.getClass());
return new ScheduledMethodRunnable(target, invocableMethod); return new ScheduledMethodRunnable(target, invocableMethod);
} }

47
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.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.aop.framework.AopProxyUtils; import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.support.AopUtils; import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
@ -98,10 +99,10 @@ public class JmsListenerAnnotationBeanPostProcessor
protected final Log logger = LogFactory.getLog(getClass()); protected final Log logger = LogFactory.getLog(getClass());
@Nullable @Nullable
private JmsListenerEndpointRegistry endpointRegistry; private String containerFactoryBeanName = DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME;
@Nullable @Nullable
private String containerFactoryBeanName = DEFAULT_JMS_LISTENER_CONTAINER_FACTORY_BEAN_NAME; private JmsListenerEndpointRegistry endpointRegistry;
private final MessageHandlerMethodFactoryAdapter messageHandlerMethodFactory = private final MessageHandlerMethodFactoryAdapter messageHandlerMethodFactory =
new MessageHandlerMethodFactoryAdapter(); new MessageHandlerMethodFactoryAdapter();
@ -124,14 +125,6 @@ public class JmsListenerAnnotationBeanPostProcessor
return LOWEST_PRECEDENCE; 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. * Set the name of the {@link JmsListenerContainerFactory} to use by default.
* <p>If none is specified, "jmsListenerContainerFactory" is assumed to be defined. * <p>If none is specified, "jmsListenerContainerFactory" is assumed to be defined.
@ -140,6 +133,14 @@ public class JmsListenerAnnotationBeanPostProcessor
this.containerFactoryBeanName = containerFactoryBeanName; 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 * Set the {@link MessageHandlerMethodFactory} to use to configure the message
* listener responsible to serve an endpoint detected by this processor. * 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) { if (this.registrar.getEndpointRegistry() == null) {
// Determine JmsListenerEndpointRegistry bean from the BeanFactory // Determine JmsListenerEndpointRegistry bean from the BeanFactory
if (this.endpointRegistry == null) { if (this.endpointRegistry == null) {
@ -193,9 +198,6 @@ public class JmsListenerAnnotationBeanPostProcessor
this.registrar.setEndpointRegistry(this.endpointRegistry); 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 // Set the custom handler method factory once resolved by the configurer
MessageHandlerMethodFactory handlerMethodFactory = this.registrar.getMessageHandlerMethodFactory(); MessageHandlerMethodFactory handlerMethodFactory = this.registrar.getMessageHandlerMethodFactory();
@ -218,9 +220,15 @@ public class JmsListenerAnnotationBeanPostProcessor
} }
@Override @Override
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException { public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (!this.nonAnnotatedClasses.contains(bean.getClass())) { if (bean instanceof AopInfrastructureBean || bean instanceof JmsListenerContainerFactory ||
Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean); bean instanceof JmsListenerEndpointRegistry) {
// Ignore AOP infrastructure such as scoped proxies.
return bean;
}
Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);
if (!this.nonAnnotatedClasses.contains(targetClass)) {
Map<Method, Set<JmsListener>> annotatedMethods = MethodIntrospector.selectMethods(targetClass, Map<Method, Set<JmsListener>> annotatedMethods = MethodIntrospector.selectMethods(targetClass,
(MethodIntrospector.MetadataLookup<Set<JmsListener>>) method -> { (MethodIntrospector.MetadataLookup<Set<JmsListener>>) method -> {
Set<JmsListener> listenerMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations( Set<JmsListener> listenerMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations(
@ -228,16 +236,15 @@ public class JmsListenerAnnotationBeanPostProcessor
return (!listenerMethods.isEmpty() ? listenerMethods : null); return (!listenerMethods.isEmpty() ? listenerMethods : null);
}); });
if (annotatedMethods.isEmpty()) { if (annotatedMethods.isEmpty()) {
this.nonAnnotatedClasses.add(bean.getClass()); this.nonAnnotatedClasses.add(targetClass);
if (logger.isTraceEnabled()) { 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 { else {
// Non-empty set of methods // Non-empty set of methods
annotatedMethods.forEach((method, listeners) -> annotatedMethods.forEach((method, listeners) ->
listeners.forEach(listener -> listeners.forEach(listener -> processJmsListener(listener, method, bean)));
processJmsListener(listener, method, bean)));
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(annotatedMethods.size() + " @JmsListener methods processed on bean '" + beanName + logger.debug(annotatedMethods.size() + " @JmsListener methods processed on bean '" + beanName +
"': " + annotatedMethods); "': " + annotatedMethods);

42
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()); assertEquals("Wrong endpoint type", MethodJmsListenerEndpoint.class, endpoint.getClass());
MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint; MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint;
assertEquals(SimpleMessageListenerTestBean.class, methodEndpoint.getBean().getClass()); assertEquals(SimpleMessageListenerTestBean.class, methodEndpoint.getBean().getClass());
assertEquals(SimpleMessageListenerTestBean.class.getMethod("handleIt", String.class), methodEndpoint.getMethod()); assertEquals(SimpleMessageListenerTestBean.class.getMethod("handleIt", String.class),
assertEquals(SimpleMessageListenerTestBean.class.getMethod("handleIt", String.class), methodEndpoint.getMostSpecificMethod()); methodEndpoint.getMethod());
assertEquals(SimpleMessageListenerTestBean.class.getMethod("handleIt", String.class),
methodEndpoint.getMostSpecificMethod());
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer(); SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
methodEndpoint.setupListenerContainer(listenerContainer); methodEndpoint.setupListenerContainer(listenerContainer);
@ -99,8 +101,10 @@ public class JmsListenerAnnotationBeanPostProcessorTests {
assertEquals("Wrong endpoint type", MethodJmsListenerEndpoint.class, endpoint.getClass()); assertEquals("Wrong endpoint type", MethodJmsListenerEndpoint.class, endpoint.getClass());
MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint; MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint;
assertEquals(MetaAnnotationTestBean.class, methodEndpoint.getBean().getClass()); assertEquals(MetaAnnotationTestBean.class, methodEndpoint.getBean().getClass());
assertEquals(MetaAnnotationTestBean.class.getMethod("handleIt", String.class), methodEndpoint.getMethod()); assertEquals(MetaAnnotationTestBean.class.getMethod("handleIt", String.class),
assertEquals(MetaAnnotationTestBean.class.getMethod("handleIt", String.class), methodEndpoint.getMostSpecificMethod()); methodEndpoint.getMethod());
assertEquals(MetaAnnotationTestBean.class.getMethod("handleIt", String.class),
methodEndpoint.getMostSpecificMethod());
assertEquals("metaTestQueue", ((AbstractJmsListenerEndpoint) endpoint).getDestination()); assertEquals("metaTestQueue", ((AbstractJmsListenerEndpoint) endpoint).getDestination());
} }
finally { finally {
@ -121,12 +125,14 @@ public class JmsListenerAnnotationBeanPostProcessorTests {
MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint; MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint;
assertTrue(AopUtils.isJdkDynamicProxy(methodEndpoint.getBean())); assertTrue(AopUtils.isJdkDynamicProxy(methodEndpoint.getBean()));
assertTrue(methodEndpoint.getBean() instanceof SimpleService); assertTrue(methodEndpoint.getBean() instanceof SimpleService);
assertEquals(SimpleService.class.getMethod("handleIt", String.class, String.class), methodEndpoint.getMethod()); assertEquals(SimpleService.class.getMethod("handleIt", String.class, String.class),
assertEquals(InterfaceProxyTestBean.class.getMethod("handleIt", String.class, String.class), methodEndpoint.getMostSpecificMethod()); methodEndpoint.getMethod());
assertEquals(InterfaceProxyTestBean.class.getMethod("handleIt", String.class, String.class),
Method m = ReflectionUtils.findMethod(endpoint.getClass(), "getDefaultResponseDestination"); methodEndpoint.getMostSpecificMethod());
ReflectionUtils.makeAccessible(m);
Object destination = ReflectionUtils.invokeMethod(m, endpoint); 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); assertEquals("SendTo annotation not found on proxy", "foobar", destination);
} }
finally { finally {
@ -147,12 +153,14 @@ public class JmsListenerAnnotationBeanPostProcessorTests {
MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint; MethodJmsListenerEndpoint methodEndpoint = (MethodJmsListenerEndpoint) endpoint;
assertTrue(AopUtils.isCglibProxy(methodEndpoint.getBean())); assertTrue(AopUtils.isCglibProxy(methodEndpoint.getBean()));
assertTrue(methodEndpoint.getBean() instanceof ClassProxyTestBean); 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),
assertEquals(ClassProxyTestBean.class.getMethod("handleIt", String.class, String.class), methodEndpoint.getMostSpecificMethod()); methodEndpoint.getMethod());
assertEquals(ClassProxyTestBean.class.getMethod("handleIt", String.class, String.class),
Method m = ReflectionUtils.findMethod(endpoint.getClass(), "getDefaultResponseDestination"); methodEndpoint.getMostSpecificMethod());
ReflectionUtils.makeAccessible(m);
Object destination = ReflectionUtils.invokeMethod(m, endpoint); 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); assertEquals("SendTo annotation not found on proxy", "foobar", destination);
} }
finally { finally {
@ -201,8 +209,8 @@ public class JmsListenerAnnotationBeanPostProcessorTests {
@Bean @Bean
public JmsListenerAnnotationBeanPostProcessor postProcessor() { public JmsListenerAnnotationBeanPostProcessor postProcessor() {
JmsListenerAnnotationBeanPostProcessor postProcessor = new JmsListenerAnnotationBeanPostProcessor(); JmsListenerAnnotationBeanPostProcessor postProcessor = new JmsListenerAnnotationBeanPostProcessor();
postProcessor.setEndpointRegistry(jmsListenerEndpointRegistry());
postProcessor.setContainerFactoryBeanName("testFactory"); postProcessor.setContainerFactoryBeanName("testFactory");
postProcessor.setEndpointRegistry(jmsListenerEndpointRegistry());
return postProcessor; return postProcessor;
} }

Loading…
Cancel
Save