From a4ac531c4a732aa28597d8480bb86601575d05cc Mon Sep 17 00:00:00 2001 From: Kicey <57286603+Kicey@users.noreply.github.com> Date: Wed, 2 Nov 2022 22:19:37 +0800 Subject: [PATCH] GH-3931: Fix meta-annotation support for @Gateway Fixes https://github.com/spring-projects/spring-integration/issues/3931 * Update test for @AliasFor support. **Cherry-pick to `5.5.x`** --- .../gateway/GatewayProxyFactoryBean.java | 6 ++- .../gateway/GatewayProxyFactoryBeanTests.java | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java index 1ba8048069..f8395edb34 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java @@ -49,6 +49,7 @@ import org.springframework.beans.factory.FactoryBean; import org.springframework.core.KotlinDetector; import org.springframework.core.MethodParameter; import org.springframework.core.ResolvableType; +import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.convert.ConversionService; import org.springframework.core.task.AsyncTaskExecutor; import org.springframework.core.task.SimpleAsyncTaskExecutor; @@ -105,6 +106,7 @@ import reactor.core.publisher.Mono; * @author Oleg Zhurakousky * @author Gary Russell * @author Artem Bilan + * @author JingPeng Xie */ public class GatewayProxyFactoryBean extends AbstractEndpoint implements TrackableComponent, FactoryBean, MethodInterceptor, BeanClassLoaderAware, @@ -478,7 +480,7 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(this.serviceInterface); for (Method method : methods) { if (Modifier.isAbstract(method.getModifiers()) - || method.getAnnotation(Gateway.class) != null + || AnnotatedElementUtils.isAnnotated(method, Gateway.class) || (method.isDefault() && this.proxyDefaultMethods)) { MethodInvocationGateway gateway = createGatewayForMethod(method); @@ -693,7 +695,7 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint } private MethodInvocationGateway createGatewayForMethod(Method method) { - Gateway gatewayAnnotation = method.getAnnotation(Gateway.class); + Gateway gatewayAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, Gateway.class); GatewayMethodMetadata methodMetadata = null; if (!CollectionUtils.isEmpty(this.methodMetadataMap)) { methodMetadata = this.methodMetadataMap.get(method.getName()); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyFactoryBeanTests.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyFactoryBeanTests.java index cccac95309..9bf0bd44a3 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyFactoryBeanTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayProxyFactoryBeanTests.java @@ -23,6 +23,10 @@ import static org.mockito.BDDMockito.willReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import java.lang.reflect.Method; import java.util.Collections; import java.util.Map; @@ -40,6 +44,7 @@ import org.springframework.beans.factory.BeanInitializationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.core.annotation.AliasFor; import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.convert.support.GenericConversionService; @@ -70,6 +75,7 @@ import org.springframework.util.ReflectionUtils; * @author Gunnar Hillert * @author Gary Russell * @author Artem Bilan + * @author JingPeng Xie */ public class GatewayProxyFactoryBeanTests { @@ -496,6 +502,20 @@ public class GatewayProxyFactoryBeanTests { assertThat(gateways.size()).isEqualTo(2); } + @Test + public void testAliasForSupport() throws NoSuchMethodException { + MessageChannel requestChannel = new DirectChannel(); + DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + beanFactory.registerSingleton("requestChannel", requestChannel); + GatewayProxyFactoryBean gpfb = new GatewayProxyFactoryBean<>( + CompositedGatewayService.class); + gpfb.setBeanFactory(beanFactory); + gpfb.afterPropertiesSet(); + Map gateways = gpfb.getGateways(); + Method sendMethod = CompositedGatewayService.class.getMethod("gatewayMethod"); + assertThat(gateways.get(sendMethod).getRequestChannel()).isEqualTo(beanFactory.getBean("requestChannel")); + } + public static void throwTestException() throws TestException { throw new TestException(); } @@ -515,6 +535,26 @@ public class GatewayProxyFactoryBeanTests { } + + @Gateway + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + @interface CompositedGateway { + + @AliasFor(annotation = Gateway.class, attribute = "requestChannel") + String requestChannelName() default ""; + + } + + + interface CompositedGatewayService { + + @CompositedGateway(requestChannelName = "requestChannel") + void gatewayMethod(); + + } + + interface HeadersParamService { Message echo(String s, @Header(MessageHeaders.TIMESTAMP) String foo);