Skip to content

Commit 5d610ac

Browse files
committed
* Meta-annotate @MessagingGateway with a @MessageEndpoint
* Alias `@MessageEndpoint.value()` with a `@Component.value()` * Alias `@MessagingGateway.name()` with a `@MessageEndpoint.value()`
1 parent 2928729 commit 5d610ac

File tree

4 files changed

+28
-13
lines changed

4 files changed

+28
-13
lines changed

spring-integration-core/src/main/java/org/springframework/integration/annotation/MessageEndpoint.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,13 +23,15 @@
2323
import java.lang.annotation.RetentionPolicy;
2424
import java.lang.annotation.Target;
2525

26+
import org.springframework.core.annotation.AliasFor;
2627
import org.springframework.stereotype.Component;
2728

2829
/**
2930
* Stereotype annotation indicating that a class is capable of serving as a
3031
* Message Endpoint.
3132
*
3233
* @author Mark Fisher
34+
* @author Artem Bilan
3335
*/
3436
@Target(ElementType.TYPE)
3537
@Retention(RetentionPolicy.RUNTIME)
@@ -41,9 +43,9 @@
4143
/**
4244
* The value may indicate a suggestion for a logical component name,
4345
* to be turned into a Spring bean in case of an autodetected component.
44-
*
4546
* @return the suggested component name, if any
4647
*/
48+
@AliasFor(annotation = Component.class)
4749
String value() default "";
4850

4951
}

spring-integration-core/src/main/java/org/springframework/integration/annotation/MessagingGateway.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2021 the original author or authors.
2+
* Copyright 2014-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,12 +21,12 @@
2121
import java.lang.annotation.RetentionPolicy;
2222
import java.lang.annotation.Target;
2323

24-
import org.springframework.stereotype.Indexed;
24+
import org.springframework.core.annotation.AliasFor;
2525

2626
/**
2727
* A stereotype annotation to provide an Integration Messaging Gateway Proxy
28-
* ({@code <gateway/>}) as an abstraction over the messaging API. The target
29-
* application's business logic may be completely unaware of the Spring Integration
28+
* as an abstraction over the messaging API. The target application's
29+
* business logic may be completely unaware of the Spring Integration
3030
* API, with the code interacting only via the interface.
3131
* <p>
3232
* Important: The {@link IntegrationComponentScan} annotation is required along with
@@ -41,17 +41,19 @@
4141
* @since 4.0
4242
*
4343
* @see IntegrationComponentScan
44+
* @see MessageEndpoint
4445
*/
4546
@Target(ElementType.TYPE)
4647
@Retention(RetentionPolicy.RUNTIME)
47-
@Indexed
48+
@MessageEndpoint
4849
public @interface MessagingGateway {
4950

5051
/**
5152
* The value may indicate a suggestion for a logical component name,
5253
* to be turned into a Spring bean in case of an autodetected component.
5354
* @return the suggested component name, if any
5455
*/
56+
@AliasFor(annotation = MessageEndpoint.class, attribute = "value")
5557
String name() default "";
5658

5759
/**

spring-integration-core/src/test/java/org/springframework/integration/configuration/EnableIntegrationTests.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@
4848
import org.springframework.beans.factory.annotation.Autowired;
4949
import org.springframework.beans.factory.annotation.Qualifier;
5050
import org.springframework.beans.factory.config.AbstractFactoryBean;
51+
import org.springframework.beans.factory.config.BeanDefinition;
5152
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
53+
import org.springframework.beans.factory.support.AbstractBeanDefinition;
54+
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
5255
import org.springframework.context.ApplicationContext;
5356
import org.springframework.context.Lifecycle;
5457
import org.springframework.context.SmartLifecycle;
@@ -64,6 +67,7 @@
6467
import org.springframework.context.expression.EnvironmentAccessor;
6568
import org.springframework.context.expression.MapAccessor;
6669
import org.springframework.core.annotation.AliasFor;
70+
import org.springframework.core.annotation.AnnotatedElementUtils;
6771
import org.springframework.core.convert.converter.Converter;
6872
import org.springframework.core.log.LogAccessor;
6973
import org.springframework.core.serializer.support.SerializingConverter;
@@ -79,6 +83,7 @@
7983
import org.springframework.integration.annotation.GatewayHeader;
8084
import org.springframework.integration.annotation.InboundChannelAdapter;
8185
import org.springframework.integration.annotation.IntegrationComponentScan;
86+
import org.springframework.integration.annotation.MessageEndpoint;
8287
import org.springframework.integration.annotation.MessagingGateway;
8388
import org.springframework.integration.annotation.Poller;
8489
import org.springframework.integration.annotation.Publisher;
@@ -143,6 +148,7 @@
143148
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
144149
import org.springframework.util.ClassUtils;
145150
import org.springframework.util.MultiValueMap;
151+
import org.springframework.util.StringUtils;
146152

147153
import reactor.core.publisher.Flux;
148154
import reactor.core.publisher.Mono;
@@ -488,6 +494,10 @@ public void testChangePatterns() {
488494

489495
@Test
490496
public void testMessagingGateway() throws InterruptedException {
497+
String gatewayBeanName = AnnotatedElementUtils.findMergedAnnotation(TestGateway.class, Component.class).value();
498+
assertThat(gatewayBeanName).isEqualTo("namedTestGateway");
499+
assertThat(this.testGateway).isSameAs(this.context.getBean(gatewayBeanName));
500+
491501
String payload = "bar";
492502
String result = this.testGateway.echo(payload);
493503
assertThat(result.substring(0, payload.length())).isEqualTo(payload.toUpperCase());
@@ -1464,7 +1474,7 @@ public interface ConditionalGateway {
14641474

14651475
}
14661476

1467-
@TestMessagingGateway
1477+
@TestMessagingGateway(name = "namedTestGateway")
14681478
public interface TestGateway {
14691479

14701480
@Gateway(headers = @GatewayHeader(name = "calledMethod", expression = "method.name"))
@@ -1494,6 +1504,9 @@ public interface TestGateway2 {
14941504
defaultHeaders = @GatewayHeader(name = "foo", value = "FOO"))
14951505
public @interface TestMessagingGateway {
14961506

1507+
@AliasFor(annotation = MessagingGateway.class)
1508+
String name() default "";
1509+
14971510
@AliasFor(annotation = MessagingGateway.class, attribute = "defaultRequestChannel")
14981511
String defaultRequestChannel() default "";
14991512

src/reference/asciidoc/gateway.adoc

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,9 @@ Along with the `@MessagingGateway` annotation you can mark a service interface w
319319

320320
Starting with version 6.0, an interface with the `@MessagingGateway` can also be marked with a `@Primary` annotation for respective configuration logic as its possible with any Spring `@Component` definition.
321321

322-
The `@MessagingGateway.name()` attribute specifies a name for the target bean registered.
323-
If it is not provided, the `@IntegrationComponentScan.nameGenerator()` (since version `6.0`) is consulted.
324-
And if that is not provided as well, an `AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR` bean, provided for the application context, is used.
325-
Otherwise, the bean name generation falls back to the `AnnotationBeanNameGenerator` which results with an uncapitalized simple class name.
326-
In other words, the current naming strategy for gateway proxy beans is aligned with standard Spring Framework `@ComponentScan` approach.
322+
The `@MessagingGateway` is meta-annotated with a `@MessageEndpoint` since version `6.0` and the `name()` attribute is, essentially, aliased to the `@Compnent.value()`.
323+
This way the bean names generating strategy for gateway proxies is realigned with the standard Spring annotation configuration for scanned and imported components.
324+
The default `AnnotationBeanNameGenerator` can be overridden globally via an `AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR` or as a `@IntegrationComponentScan.nameGenerator()` attribute.
327325

328326
NOTE: If you have no XML configuration, the `@EnableIntegration` annotation is required on at least one `@Configuration` class.
329327
See <<./overview.adoc#configuration-enable-integration,Configuration and `@EnableIntegration`>> for more information.

0 commit comments

Comments
 (0)