INT-4556: Fix messaging anns for FactoryBeans

JIRA: https://jira.spring.io/browse/INT-4556

We definitely need to resolve a `@Bean` method to the target object to
be sure do not create a new `MessageHandler` bean.

**Cherry-pick to 5.0.x**
This commit is contained in:
Artem Bilan
2018-11-16 16:17:03 -05:00
committed by Gary Russell
parent d1b3046638
commit 47a4b28f1f
5 changed files with 44 additions and 31 deletions

View File

@@ -128,16 +128,13 @@ public abstract class AbstractMethodAnnotationPostProcessor<T extends Annotation
@Override
public Object postProcess(Object bean, String beanName, Method method, List<Annotation> annotations) {
if (this.beanAnnotationAware() && AnnotatedElementUtils.isAnnotated(method, Bean.class.getName())) {
Object sourceHandler = null;
if (beanAnnotationAware() && AnnotatedElementUtils.isAnnotated(method, Bean.class.getName())) {
if (!this.beanFactory.containsBeanDefinition(resolveTargetBeanName(method))) {
this.logger.debug("Skipping endpoint creation; perhaps due to some '@Conditional' annotation.");
return null;
}
}
Object sourceHandler = null;
if (beanAnnotationAware() && AnnotatedElementUtils.isAnnotated(method, Bean.class.getName())) {
if (MessageHandler.class.isAssignableFrom(method.getReturnType())) {
else {
sourceHandler = resolveTargetBeanFromMethodWithBeanAnnotation(method);
}
}
@@ -159,12 +156,15 @@ public abstract class AbstractMethodAnnotationPostProcessor<T extends Annotation
if (handler instanceof AbstractMessageProducingHandler || handler instanceof AbstractMessageRouter) {
String sendTimeout = MessagingAnnotationUtils.resolveAttribute(annotations, "sendTimeout", String.class);
if (sendTimeout != null) {
Long value = Long.valueOf(this.beanFactory.resolveEmbeddedValue(sendTimeout));
if (handler instanceof AbstractMessageProducingHandler) {
((AbstractMessageProducingHandler) handler).setSendTimeout(value);
}
else {
((AbstractMessageRouter) handler).setSendTimeout(value);
String resolvedValue = this.beanFactory.resolveEmbeddedValue(sendTimeout);
if (resolvedValue != null) {
long value = Long.parseLong(resolvedValue);
if (handler instanceof AbstractMessageProducingHandler) {
((AbstractMessageProducingHandler) handler).setSendTimeout(value);
}
else {
((AbstractMessageRouter) handler).setSendTimeout(value);
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2015 the original author or authors.
* Copyright 2014-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.
@@ -37,6 +37,7 @@ import org.springframework.util.StringUtils;
* Post-processor for the {@link BridgeFrom @BridgeFrom} annotation.
*
* @author Artem Bilan
*
* @since 4.0
*/
public class BridgeFromAnnotationPostProcessor extends AbstractMethodAnnotationPostProcessor<BridgeFrom> {
@@ -78,4 +79,9 @@ public class BridgeFromAnnotationPostProcessor extends AbstractMethodAnnotationP
return handler;
}
@Override
protected Object resolveTargetBeanFromMethodWithBeanAnnotation(Method method) {
return null;
}
}

View File

@@ -72,13 +72,11 @@ public class MessagingAnnotationPostProcessor implements BeanPostProcessor, Bean
protected final Log logger = LogFactory.getLog(this.getClass()); // NOSONAR
private final Map<Class<? extends Annotation>, MethodAnnotationPostProcessor<?>> postProcessors =
new HashMap<Class<? extends Annotation>, MethodAnnotationPostProcessor<?>>();
private final Map<Class<? extends Annotation>, MethodAnnotationPostProcessor<?>> postProcessors = new HashMap<>();
private ConfigurableListableBeanFactory beanFactory;
private final Set<Class<?>> noAnnotationsCache =
Collections.newSetFromMap(new ConcurrentHashMap<Class<?>, Boolean>(256));
private final Set<Class<?>> noAnnotationsCache = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
@Override
public void setBeanFactory(BeanFactory beanFactory) {
@@ -222,13 +220,15 @@ public class MessagingAnnotationPostProcessor implements BeanPostProcessor, Bean
*/
protected List<Annotation> getAnnotationChain(Method method, Class<? extends Annotation> annotationType) {
Annotation[] annotations = AnnotationUtils.getAnnotations(method);
List<Annotation> annotationChain = new LinkedList<Annotation>();
Set<Annotation> visited = new HashSet<Annotation>();
for (Annotation ann : annotations) {
recursiveFindAnnotation(annotationType, ann, annotationChain, visited);
if (annotationChain.size() > 0) {
Collections.reverse(annotationChain);
return annotationChain;
List<Annotation> annotationChain = new LinkedList<>();
if (annotations != null) {
Set<Annotation> visited = new HashSet<>();
for (Annotation ann : annotations) {
recursiveFindAnnotation(annotationType, ann, annotationChain, visited);
if (annotationChain.size() > 0) {
Collections.reverse(annotationChain);
return annotationChain;
}
}
}
return annotationChain;

View File

@@ -52,8 +52,8 @@ public class ServiceActivatorAnnotationPostProcessor extends AbstractMethodAnnot
protected MessageHandler createHandler(Object bean, Method method, List<Annotation> annotations) {
AbstractReplyProducingMessageHandler serviceActivator;
if (AnnotatedElementUtils.isAnnotated(method, Bean.class.getName())) {
final Object target = this.resolveTargetBeanFromMethodWithBeanAnnotation(method);
serviceActivator = this.extractTypeIfPossible(target, AbstractReplyProducingMessageHandler.class);
final Object target = resolveTargetBeanFromMethodWithBeanAnnotation(method);
serviceActivator = extractTypeIfPossible(target, AbstractReplyProducingMessageHandler.class);
if (serviceActivator == null) {
if (target instanceof MessageHandler) {
/*

View File

@@ -111,6 +111,7 @@ import org.springframework.integration.endpoint.MethodInvokingMessageSource;
import org.springframework.integration.endpoint.PollingConsumer;
import org.springframework.integration.expression.SpelPropertyAccessorRegistrar;
import org.springframework.integration.gateway.GatewayProxyFactoryBean;
import org.springframework.integration.handler.ServiceActivatingHandler;
import org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice;
import org.springframework.integration.history.MessageHistory;
import org.springframework.integration.history.MessageHistoryConfigurer;
@@ -421,11 +422,17 @@ public class EnableIntegrationTests {
assertEquals("FOO", message.getHeaders().get("foo"));
MessagingTemplate messagingTemplate = new MessagingTemplate(this.controlBusChannel);
assertFalse(messagingTemplate.convertSendAndReceive("@lifecycle.isRunning()", Boolean.class));
this.controlBusChannel.send(new GenericMessage<String>("@lifecycle.start()"));
assertTrue(messagingTemplate.convertSendAndReceive("@lifecycle.isRunning()", Boolean.class));
this.controlBusChannel.send(new GenericMessage<String>("@lifecycle.stop()"));
assertFalse(messagingTemplate.convertSendAndReceive("@lifecycle.isRunning()", Boolean.class));
assertEquals(false, messagingTemplate.convertSendAndReceive("@lifecycle.isRunning()", Boolean.class));
this.controlBusChannel.send(new GenericMessage<>("@lifecycle.start()"));
assertEquals(true, messagingTemplate.convertSendAndReceive("@lifecycle.isRunning()", Boolean.class));
this.controlBusChannel.send(new GenericMessage<>("@lifecycle.stop()"));
assertEquals(false, messagingTemplate.convertSendAndReceive("@lifecycle.isRunning()", Boolean.class));
Map<String, ServiceActivatingHandler> beansOfType =
this.context.getBeansOfType(ServiceActivatingHandler.class);
assertFalse(beansOfType.keySet()
.contains("enableIntegrationTests.ContextConfiguration2.controlBus.serviceActivator.handler"));
}
@Test