跳到主要内容

消息元注解

QWen Plus 中英对照 Messaging Meta-Annotations

从 4.0 版本开始,所有消息注解都可以配置为元注解,所有用户定义的消息注解都可以定义相同的属性以覆盖其默认值。此外,元注解可以分层配置,如下例所示:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ServiceActivator(inputChannel = "annInput", outputChannel = "annOutput")
public @interface MyServiceActivator {

String[] adviceChain = { "annAdvice" };
}

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@MyServiceActivator
public @interface MyServiceActivator1 {

String inputChannel();

String outputChannel();
}
...

@MyServiceActivator1(inputChannel = "inputChannel", outputChannel = "outputChannel")
public Object service(Object payload) {
...
}
java

分层配置元注解可以让用户为各种属性设置默认值,并且可以将框架的 Java 依赖隔离到用户注解中,避免在用户类中使用这些依赖。如果框架发现一个带有用户注解的方法,而该用户注解又带有框架的元注解,则该方法将被视为直接使用了框架注解。

@Bean 方法上的注解

从 4.0 版本开始,你可以在 @Configuration 类中的 @Bean 方法定义上配置消息注解,以根据 bean 而不是方法生成消息端点。当 @Bean 定义是“开箱即用”的 MessageHandler 实例(如 AggregatingMessageHandlerDefaultMessageSplitter 等),Transformer 实例(如 JsonToObjectTransformerClaimCheckOutTransformer 等)和 MessageSource 实例(如 FileReadingMessageSourceRedisStoreMessageSource 等)时,这非常有用。以下示例展示了如何将消息注解与 @Bean 注解一起使用:

@Configuration
@EnableIntegration
public class MyFlowConfiguration {

@Bean
@InboundChannelAdapter(value = "inputChannel", poller = @Poller(fixedDelay = "1000"))
public MessageSource<String> consoleSource() {
return CharacterStreamReadingMessageSource.stdin();
}

@Bean
@Transformer(inputChannel = "inputChannel", outputChannel = "httpChannel")
public ObjectToMapTransformer toMapTransformer() {
return new ObjectToMapTransformer();
}

@Bean
@ServiceActivator(inputChannel = "httpChannel")
public HttpRequestExecutingMessageHandler httpHandler() {
HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler("https://foo/service");
handler.setExpectedResponseType(String.class);
handler.setOutputChannelName("outputChannel");
return handler;
}

@Bean
@ServiceActivator(inputChannel = "outputChannel")
public LoggingHandler loggingHandler() {
return new LoggingHandler("info");
}

}
java

版本 5.0 引入了对带有 @InboundChannelAdapter 注解的 @Bean 的支持,该 @Bean 返回 java.util.function.Supplier,可以生成 POJO 或 Message。以下示例展示了如何使用这种组合:

@Configuration
@EnableIntegration
public class MyFlowConfiguration {

@Bean
@InboundChannelAdapter(value = "inputChannel", poller = @Poller(fixedDelay = "1000"))
public Supplier<String> pojoSupplier() {
return () -> "foo";
}

@Bean
@InboundChannelAdapter(value = "inputChannel", poller = @Poller(fixedDelay = "1000"))
public Supplier<Message<String>> messageSupplier() {
return () -> new GenericMessage<>("foo");
}
}
java

元注解规则也适用于 @Bean 方法(可以将前面描述的 @MyServiceActivator 注解应用于一个 @Bean 定义)。

备注

当你在消费者 @Bean 定义上使用这些注解时,如果 bean 定义返回一个适当的 MessageHandler(取决于注解类型),你必须在 MessageHandler @Bean 定义本身上设置属性(如 outputChannelrequiresReplyorder 等)。只有以下注解属性会被使用:adviceChainautoStartupinputChannelphasepoller。所有其他属性都是为处理程序设置的。

备注

bean 名称是使用以下算法生成的:

  • MessageHandler (MessageSource) @Bean 从方法名称或 @Bean 上的 name 属性获取其标准名称。这就像 @Bean 方法上没有消息注解一样工作。

  • AbstractEndpoint 的 bean 名称是根据以下模式生成的:[@Bean 名称].[小写注解类短名称]。例如,consoleSource() 定义 之前显示SourcePollingChannelAdapter 端点会得到一个名为 consoleSource.inboundChannelAdapter 的 bean 名称。与 POJO 方法不同,bean 方法名称不包含在端点 bean 名称中。另请参阅 端点 Bean 名称

  • 如果 @Bean 不能直接用于目标端点(不是 MessageSourceAbstractReplyProducingMessageHandlerAbstractMessageRouter 的实例),则注册相应的 AbstractStandardMessageHandlerFactoryBean 来委托给此 @Bean。此包装器的 bean 名称根据以下模式生成:[@Bean 名称].[小写注解类短名称].[处理器 (或 源)]

important

@Bean 定义上使用这些注解时,inputChannel 必须引用一个已声明的 bean。如果通道尚未在应用程序上下文中,则会自动声明。

备注

使用 Java 配置时,你可以在 @Bean 方法级别上使用任何 @Conditional(例如,@Profile)定义,以跳过某些条件原因的 bean 注册。以下示例展示了如何做到这一点:

@Bean
@ServiceActivator(inputChannel = "skippedChannel")
@Profile("thing")
public MessageHandler skipped() {
return System.out::println;
}
java

结合现有的 Spring 容器逻辑,基于 @ServiceActivator 注解的消息端点 bean 也不会被注册。

使用注解创建桥

从 4.0 版本开始,Java 配置提供了 @BridgeFrom@BridgeTo @Bean 方法注解,用于在 @Configuration 类中标记 MessageChannel beans。这些注解确实是为了完整性而存在,提供了一种方便的机制来声明 BridgeHandler 及其消息端点配置:

@Bean
public PollableChannel bridgeFromInput() {
return new QueueChannel();
}

@Bean
@BridgeFrom(value = "bridgeFromInput", poller = @Poller(fixedDelay = "1000"))
public MessageChannel bridgeFromOutput() {
return new DirectChannel();
}
@Bean
public QueueChannel bridgeToOutput() {
return new QueueChannel();
}

@Bean
@BridgeTo("bridgeToOutput")
public MessageChannel bridgeToInput() {
return new DirectChannel();
}
java

你也可以将这些注解用作元注解。

建议标注的端点