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 依赖项隔离到用户标注,避免在用户类中使用它们。如果框架使用具有框架元标注的用户标注找到了一个方法,则该方法的处理与使用框架标注直接对该方法执行标注一样。

Annotations on @Bean Methods

从 4.0 版本开始,可以针对 @Configuration 类中的 @Bean 方法定义配置消息传递标注,以基于 Bean(而不是方法)生成消息端点。在 @Bean 定义是 “out-of-the-box” 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");
    }

}

5.0 版本引入了对使用 @InboundChannelAdapter 标注的 @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");
    }
}

元注释规则也可以对 @Bean 方法进行处理(可以在 @Bean 定义中应用 @MyServiceActivator 注释 described earlier)。

当您对使用者 @Bean 定义使用这些注释时,如果 bean 定义返回一个相应的 MessageHandler(取决于注释类型),您必须在 MessageHandler @Bean 定义本身上设置属性(如 outputChannelrequiresReplyorder 和其他)。仅使用以下注释属性:adviceChainautoStartupinputChannelphasepoller。所有其他属性都适用于处理程序。

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

  • MessageHandler (MessageSource) @Bean@Bean 上的方法名称或 name 特性中获取自己的标准名称。这如同 @Bean 方法上没有消息传递注解。

  • AbstractEndpoint bean 名称按照以下模式生成: [@Bean name].[decapitalizedAnnotationClassShortName]。例如,consoleSource() 定义 shown earlierSourcePollingChannelAdapter 端点得到一个 bean 名称 consoleSource.inboundChannelAdapter。与 POJO 方法不同,bean 方法名称不包括在端点 bean 名称中。另请参见 Endpoint Bean Names

  • 如果 @Bean 不能直接在目标端点中使用(不是 MessageSourceAbstractReplyProducingMessageHandlerAbstractMessageRouter 的实例),则会注册一个相应的 AbstractStandardMessageHandlerFactoryBean 委托给这个 @Bean。此包装器的 bean 名称按照以下模式生成: [@Bean name].[decapitalizedAnnotationClassShortName].[handler (or source)]

当在 @Bean 定义上使用这些注释时,inputChannel 必须引用声明的 bean。如果通道在应用程序上下文中不存在,则它们将自动声明。

使用 Java 配置,可以在 @Bean 方法级别上使用任何 @Conditional(例如,@Profile)定义,以便在某些条件原因下跳过 Bean 注册。以下示例演示了如何执行此操作:

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

与现有的 Spring 容器逻辑结合使用时,还会取消注册消息传递端点 Bean(基于 @ServiceActivator 标注)。

Creating a Bridge with Annotations

从 4.0 版本开始,Java 配置提供 @BridgeFrom@BridgeTo @Bean 方法标注,以便在 @Configuration 类中标记 MessageChannel Bean。这些真正存在是为了完整性,提供了一种便利的机制来声明 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();
}

也可以将这些标注用作元标注。

Advising Annotated Endpoints