配置

配置

Spring Integration 提供多种配置选项。 你选择哪种方式取决于你的具体需求以及你喜欢的工作层级。 和Spring框架一样,你可以根据当前问题混合使用各种技术。 例如,你可以选择基于XSD的命名空间进行大部分配置,并结合少数用注释配置的对象。 两者尽可能保持一致的命名。 XSD 模式定义的 XML 元素与注释名称匹配,这些 XML 元素的属性也与注释属性名称匹配。 你也可以直接使用 API,但我们预计大多数开发者会选择更高级的选项之一,或者结合命名空间和注释驱动的配置。spring-doc.cadn.net.cn

命名空间支持

你可以用直接映射到企业集成术语和概念的XML元素配置Spring Integration组件。 在许多情况下,元素名称与《企业集成模式》一书中的名称相符。spring-doc.cadn.net.cn

要在你的 Spring 配置文件中启用 Spring Integration 的核心命名空间支持,请在顶层的“beans”元素中添加以下命名空间引用和模式映射:spring-doc.cadn.net.cn

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:int="http://www.springframework.org/schema/integration"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/integration
           https://www.springframework.org/schema/integration/spring-integration.xsd">

(我们特别强调了春季整合特有的线条。)spring-doc.cadn.net.cn

你可以在“xmlns:”之后选择任何名字。 我们使用智力(积分的缩写)为了更清楚,但你可能更喜欢另一个缩写。 另一方面,如果你使用XML编辑器或IDE支持,自动补全的可用性可能会让你为了清晰起见而选择更长的名称。 或者,您也可以创建配置文件,使用 Spring Integration 模式作为主命名空间,如下示例所示:spring-doc.cadn.net.cn

<beans:beans xmlns="http://www.springframework.org/schema/integration"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:beans="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/integration
           https://www.springframework.org/schema/integration/spring-integration.xsd">

(我们特别强调了春季整合特有的线条。)spring-doc.cadn.net.cn

使用该替代方案时,Spring 集成元素无需前缀。 另一方面,如果你在同一配置文件中定义通用的 Spring Bean,bean 元素需要前缀(<豆子:豆子....../>). 由于通常基于责任层或架构层对配置文件进行模块化是个好主意,你可能会觉得在集成型配置文件中使用后一种方法更合适,因为这些文件中很少需要通用豆子。 在本文档中,我们假设集成命名空间是主命名空间。spring-doc.cadn.net.cn

Spring Integration 提供了许多其他命名空间。 事实上,每个支持命名空间的适配器类型(如 JMS、文件等)都会在一个独立的模式中定义其元素。 为了使用这些元素,可以添加必要的命名空间,并使用XMLSNS元素及相应的schemaLocation映射。 例如,以下根元素展示了若干命名空间声明:spring-doc.cadn.net.cn

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:int="http://www.springframework.org/schema/integration"
  xmlns:int-file="http://www.springframework.org/schema/integration/file"
  xmlns:int-jms="http://www.springframework.org/schema/integration/jms"
  xmlns:int-mail="http://www.springframework.org/schema/integration/mail"
  xmlns:int-ws="http://www.springframework.org/schema/integration/ws"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/integration
    https://www.springframework.org/schema/integration/spring-integration.xsd
    http://www.springframework.org/schema/integration/file
    https://www.springframework.org/schema/integration/file/spring-integration-file.xsd
    http://www.springframework.org/schema/integration/jms
    https://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
    http://www.springframework.org/schema/integration/mail
    https://www.springframework.org/schema/integration/mail/spring-integration-mail.xsd
    http://www.springframework.org/schema/integration/ws
    https://www.springframework.org/schema/integration/ws/spring-integration-ws.xsd">
 ...
</beans>

本参考手册提供了各章节中各元素的具体示例。 这里最重要的是每个命名空间URI和模式位置的命名一致性。spring-doc.cadn.net.cn

配置任务调度器

在春季集成中,应用上下文作为消息总线,你只需考虑几种配置选项。 首先,你可能想控制中央任务调度器实例。 你可以通过提供一颗名为任务调度器. 这也被定义为常数,具体如下:spring-doc.cadn.net.cn

IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME

默认情况下,Spring 集成依赖于ThreadPoolTaskScheduler,如 Spring Framework 参考手册中任务执行与调度部分所述。 那个默认情况任务调度器自动启动时有十个线程,但请参见全局属性。 如果你提供自己的任务调度器实例中,你可以将“autoStartup”属性设置为false或者提供你自己的泳池规模值。spring-doc.cadn.net.cn

当轮询消费者在其配置中提供显式任务执行器引用时,处理程序方法的调用发生在该执行器的线程池内,而非主调度池。 然而,当端点的轮询器没有任务执行器时,该任务会被主调度器的某个线程调用。spring-doc.cadn.net.cn

不要在轮询线程上运行长时间运行的任务。 改用任务执行器吧。 如果你有很多轮询端点,可能会导致线程饥饿,除非你增加线程池大小。 此外,投票消费者有默认选项收到超时一秒钟。 由于轮询线程在此期间会被阻塞,我们建议当存在多个此类端点时使用任务执行器,以避免饥饿。 或者,你也可以减少收到超时.
如果端点的输入信道是基于队列的(即可轮询)信道之一,则称该端点为轮询消费者。 事件驱动消费者是指输入信道中设有调度者而非队列(换句话说,他们是可订阅的)。 此类端点没有轮询器配置,因为它们的处理程序是直接调用的。

在JEE容器里跑步时,可能需要用Spring的TimerManagerTaskScheduler,如此处所述,代替默认任务调度器. 为此,请为你的环境定义一个带有相应JNDI名称的豆子,如下示例所示:spring-doc.cadn.net.cn

<bean id="taskScheduler" class="org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler">
    <property name="jndiName" value="tm/MyTimerManager" />
    <property name="resourceRef" value="true" />
</bean>
当成为习俗时任务调度器在应用上下文中配置(如上所述)DefaultManagedTaskScheduler建议为其提供消息发布错误处理 (integrationMessagePublishingErrorHandlerBEAN)能够处理异常,作为ErrorMessage 会发送到错误通道,就像默认的“TaskScheduler” 一样BEAN 由 Framework 提供。

全局属性

某些全局框架属性可以通过在类路径上提供属性文件来覆盖。spring-doc.cadn.net.cn

默认属性可以找到org.springframework.integration.context.IntegrationProperties类。 以下列表显示了默认值:spring-doc.cadn.net.cn

spring.integration.channels.autoCreate=true (1)
spring.integration.channels.maxUnicastSubscribers=0x7fffffff (2)
spring.integration.channels.maxBroadcastSubscribers=0x7fffffff (3)
spring.integration.taskScheduler.poolSize=10 (4)
spring.integration.messagingTemplate.throwExceptionOnLateReply=false (5)
spring.integration.readOnly.headers= (6)
spring.integration.endpoints.noAutoStartup= (7)
spring.integration.channels.error.requireSubscribers=true (8)
spring.integration.channels.error.ignoreFailures=true (9)
1 当属实时,输入通道实例自动声明为直达频道当应用上下文中未明确找到的实例。
2 设置默认允许的订阅人数,例如:直达频道. 它可以用来避免无意中订阅多个终端到同一频道。 你可以通过设置最大订阅者属性。
3 该属性提供了例如,允许的默认订阅人数发布订阅频道. 它可以用来避免无意中订阅超过预期数量的终端数。 你可以通过设置最大订阅者属性。
4 默认情况下可用的线程数量任务调度器豆。 参见配置任务调度器
5 什么时候true当网关不期待回复(因为发送线程超时或已收到回复)时,抵达网关回复通道的消息会抛出异常。
6 一个逗号分隔的消息头名列表,不应被填充于消息在一个头部复制作中的实例。 该列表被以下机构使用默认信息建设工厂Beans并被繁殖到集成消息头访问器实例(参见消息头访问器应用程序接口)用于构建消息,通过以下方式消息构建器(参见消息构建器辅助类). 默认情况下,只有MessageHeaders.ID消息头部.时间戳在消息构建过程中不会被复制。 自4.3.2版本起。
7 逗号分隔的列表摘要终点Bean 给图案命名(xxx*,xxx,*xxxxxx*yyy)在应用启动时不应自动启动。 你之后可以通过控制总线(参见控制总线),根据它们与SmartLifecycleRoleController(参见端点角色),或由生命周期豆子注射。 你可以通过指定 来显式覆盖该全局属性的影响自动启动XML 注释或自动启动注释属性或调用AbstractEndpoint.setAutoStartup()在豆子的定义中。 自4.3.12版本起。
8 一个布尔标志来表示默认的全局errorChannel必须配置为要求订阅者选择。 自5.4.3版本起。 更多信息请参见错误处理
9 一个布尔标志来表示默认的全局errorChannel必须忽略调度错误,并将消息传递给下一个处理器。 自5.5版本起,

这些属性可以通过添加 a 来覆盖/META-INF/spring.integration.properties文件到类通路或IntegrationContextUtils.INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME豆子org.springframework.integration.context.IntegrationProperties实例。 你不必提供所有属性——只需提供你想要覆盖的那些。spring-doc.cadn.net.cn

从5.1版本开始,所有合并后的全局属性在应用上下文启动后都会在日志中打印出来,当时调试逻辑电平被打开用于org.springframework.integration类别。 输出如下:spring-doc.cadn.net.cn

Spring Integration global properties:

spring.integration.endpoints.noAutoStartup=fooService*
spring.integration.taskScheduler.poolSize=20
spring.integration.channels.maxUnicastSubscribers=0x7fffffff
spring.integration.channels.autoCreate=true
spring.integration.channels.maxBroadcastSubscribers=0x7fffffff
spring.integration.readOnly.headers=
spring.integration.messagingTemplate.throwExceptionOnLateReply=true

注释支持

除了支持XML命名空间配置消息端点外,你还可以使用注释。 首先,Spring 集成提供了类级@MessageEndpoint作为一种刻板印象注释,意味着它本身也用斯普林的注释@Component注释,因此在Spring的组件扫描中自动被识别为豆子定义。spring-doc.cadn.net.cn

更重要的是各种方法级注释。 它们表明注释方法能够处理消息。 以下示例展示了类级和方法级注释:spring-doc.cadn.net.cn

@MessageEndpoint
public class FooService {

    @ServiceActivator
    public void processMessage(Message message) {
        ...
    }
}

该方法“处理”消息的具体含义取决于具体的注释。 Spring 集成中可用的注释包括:spring-doc.cadn.net.cn

如果你结合使用XML配置和注释,那@MessageEndpoint不需要注释。 如果你想从裁判a的属性<服务激活器/>元素,你只能提供方法级注释。 在这种情况下,即使没有方法级属性,注释也能防止歧义<服务激活器/>元素。

在大多数情况下,带注释的处理程序方法不应要求消息类型作为其参数。 相反,方法参数类型可以匹配消息的有效载荷类型,如下示例所示:spring-doc.cadn.net.cn

public class ThingService {

    @ServiceActivator
    public void bar(Thing thing) {
        ...
    }

}

当方法参数应从消息头另一种选择是使用参数级@Header注解。 一般来说,带有 Spring Integration 注释的方法可以接受消息本身、消息有效载荷,或一个头部值(其中@Header)作为参数。 事实上,该方法可以接受组合,如下示例所示:spring-doc.cadn.net.cn

public class ThingService {

    @ServiceActivator
    public void otherThing(String payload, @Header("x") int valueX, @Header("y") int valueY) {
        ...
    }

}

你也可以使用@Headers注释以提供所有消息头部作为地图,如下示例所示:spring-doc.cadn.net.cn

public class ThingService {

    @ServiceActivator
    public void otherThing(String payload, @Headers Map<String, Object> headerMap) {
        ...
    }

}
注释的值也可以是 SpEL 表达式(例如,someHeader.toUpperCase()),当你希望在注入前作头部值时非常有用。 它还提供一个可选的必填属性,指定属性值是否必须在头部中可用。 该项的默认值必填财产是true.

对于其中若干注释,当消息处理方法返回非空值时,端点尝试发送回复。 这在两个配置选项(命名空间和注释)中都是一致的,因为如果有的话,会使用该端点的输出通道,并且REPLY_CHANNEL消息头值作为备用。spring-doc.cadn.net.cn

端点上的输出通道与回复通道消息头的组合使得流水线方法成为可能,即多个组件拥有一个输出通道,最终组件允许返回消息转发到回复通道(如原始请求消息中指定)。 换句话说,最终组件依赖于原始发送方提供的信息,因此可以动态支持任意数量的客户端。 这是退货地址模式的一个例子。

除了这里展示的例子外,这些注释还支持输入通道输出通道以下示例展示了性质:spring-doc.cadn.net.cn

@Service
public class ThingService {

    @ServiceActivator(inputChannel="input", outputChannel="output")
    public void otherThing(String payload, @Headers Map<String, Object> headerMap) {
        ...
    }

}

这些注释的处理会生成与相应XML组件相同的豆子——摘要终点实例和消息处理器实例(或消息源为入站通道适配器实例)。 看注释@Bean方法. 豆子名称由以下模式生成:[组件名称]。[方法名称]。[去大写AnnotationClassShortName]. 在前面的例子中,豆子的名字是thingService.otherThing.serviceActivator对于摘要终点以及同名加上一个额外的。处理器 (。源) 后缀消息处理器 (消息源) 豆子。 这样的名称可以通过以下方式进行定制@EndpointId注释与这些消息注释并行。 这消息处理器实例(消息源实例)也可以通过消息历史记录被追踪。spring-doc.cadn.net.cn

从4.0版本开始,所有消息注释都提供SmartLifecycle选项(自动启动阶段)以便允许对应用上下文初始化进行端点生命周期控制。 他们默认是true0分别。 改变端点的状态(例如:开始()停止()),你可以通过使用豆子工厂(或自接线)并调用这些方法。 或者,你也可以向控制总线(参见控制总线) 为此,你应该使用豆名前面提到的。spring-doc.cadn.net.cn

在解析上述注释后自动创建的通道(当未配置特定通道豆)及其对应的消费者端点,在上下文初始化接近尾声时被声明为豆子。 这些豆子可以在其他服务中自动接线,但必须标注@Lazy注释是因为定义通常在正常的自动配线处理过程中尚未可用。spring-doc.cadn.net.cn

@Autowired
@Lazy
@Qualifier("someChannel")
MessageChannel someChannel;
...

@Bean
Thing1 dependsOnSPCA(@Qualifier("someInboundAdapter") @Lazy SourcePollingChannelAdapter someInboundAdapter) {
    ...
}

从6.0版本开始,所有消息注释都是@Repeatable现在,可以在同一服务方法上声明多个相同类型的节点,目的是创建与重复这些注释数量相同的端点:spring-doc.cadn.net.cn

@Transformer(inputChannel = "inputChannel1", outputChannel = "outputChannel1")
@Transformer(inputChannel = "inputChannel2", outputChannel = "outputChannel2")
public String transform(String input) {
    return input.toUpperCase();
}

使用@Poller注解

在 Spring 集成 4.0 之前,消息注释要求输入通道可以引用订阅频道. 为Pollable频道实例,一个<in:bridge/>配置 元素<in:poller/>使复合端点为民调消费者. 4.0 版本引入了@Poller注释以允许配置轮询者属性直接出现在消息注释上,如下示例所示:spring-doc.cadn.net.cn

public class AnnotationService {

    @Transformer(inputChannel = "input", outputChannel = "output",
        poller = @Poller(maxMessagesPerPoll = "${poller.maxMessagesPerPoll}", fixedDelay = "${poller.fixedDelay}"))
    public String handle(String payload) {
        ...
    }
}

@Poller注释仅提供简单Poller元数据选项。 你可以配置@Poller注释的属性(maxMessagesPerPoll,fixedDelay,固定利率克朗)带有属性占位符。 此外,从5.1版本开始,收到超时选项为民调消费者也提供了S。 如果需要提供更多轮询选项(例如,交易,咨询链,错误处理以及其他),你应该配置Poller元数据作为一种通用豆,并使用其豆名作为@Poller属性。 在这种情况下,不允许其他属性(它们必须在Poller元数据豆)。 注意,如果输入通道Pollable频道@Poller是配置好的,是默认的Poller元数据如果在应用上下文中存在,则被使用。 通过使用@Configuration注释,使用类似以下示例的代码:spring-doc.cadn.net.cn

@Bean(name = PollerMetadata.DEFAULT_POLLER)
public PollerMetadata defaultPoller() {
    PollerMetadata pollerMetadata = new PollerMetadata();
    pollerMetadata.setTrigger(new PeriodicTrigger(10));
    return pollerMetadata;
}

以下示例展示了如何使用默认轮询器:spring-doc.cadn.net.cn

public class AnnotationService {

    @Transformer(inputChannel = "aPollableChannel", outputChannel = "output")
    public String handle(String payload) {
        ...
    }
}

以下示例展示了如何使用命名轮询器:spring-doc.cadn.net.cn

@Bean
public PollerMetadata myPoller() {
    PollerMetadata pollerMetadata = new PollerMetadata();
    pollerMetadata.setTrigger(new PeriodicTrigger(1000));
    return pollerMetadata;
}

以下示例展示了使用默认轮询器的端点:spring-doc.cadn.net.cn

public class AnnotationService {

    @Transformer(inputChannel = "aPollableChannel", outputChannel = "output"
                           poller = @Poller("myPoller"))
    public String handle(String payload) {
         ...
    }
}

从4.3.3版本开始,@Poller注释具有errorChannel属性以便更易配置底层消息发布错误处理. 该属性起到相同的作用错误信道<poller>XML组件。 更多信息请参见端点命名空间支持spring-doc.cadn.net.cn

poller()消息注释上的属性与响应式()属性。 更多信息请见下一节。spring-doc.cadn.net.cn

@Reactive注解

ReactiveStreamsConsumer自5.0版本以来就已存在,但仅在端点的输入通道为流信息频道(或者任何org.reactivestreams.出版商实现)。 从5.3版本开始,当目标消息处理程序是响应式消息处理器与输入通道类型无关。 这@Reactive子注释(类似上述)@Poller)自5.5版本起,已为所有消息注释引入。 它接受可选的功能<?超级Flux<Message<?>>,?扩展出版商<信息<?>>>BEAN 引用,且独立于输入通道类型和消息处理程序,将目标端点转换为ReactiveStreamsConsumer实例。 该函数来自Flux.transform()运算符以应用一些自定义(publishOn(),doOnNext(),log(),重试()等等)在输入通道的无功流源上。spring-doc.cadn.net.cn

以下示例演示了如何独立于最终订阅者和生产者将发布线程从输入通道切换到直达频道:spring-doc.cadn.net.cn

@Bean
public Function<Flux<?>, Flux<?>> publishOnCustomizer() {
    return flux -> flux.publishOn(Schedulers.parallel());
}

@ServiceActivator(inputChannel = "directChannel", reactive = @Reactive("publishOnCustomizer"))
public void handleReactive(String payload) {
    ...
}

响应式()消息注释上的属性与poller()属性。 看使用@Poller注解以及反应式流支持以获取更多信息。spring-doc.cadn.net.cn

使用@InboundChannelAdapter注解

4.0 版本引入了@InboundChannelAdapter方法级注释。 它产生SourcePollingChannelAdapter基于MethodInvokingMessageSource对于注释法。 该注释是<int:入站通道适配器>XML 组件和具有相同的限制:方法不能有参数,返回类型也不能是无效. 它有两个特点:(要求消息频道豆名)和轮询者(可选@Poller注释,如前所述)。 如果你需要提供一些消息头,使用留言<?>返回类型并使用消息构建器以建造留言<?>. 使用消息构建器你可以配置消息头. 以下示例展示了如何使用@InboundChannelAdapter注解:spring-doc.cadn.net.cn

@InboundChannelAdapter("counterChannel")
public Integer count() {
    return this.counter.incrementAndGet();
}

@InboundChannelAdapter(value = "fooChannel", poller = @Poller(fixed-rate = "5000"))
public String foo() {
    return "foo";
}

4.3 版本引入了渠道别名注释属性,以提供更好的源代码可读性。 还有,目标消息频道豆子在SourcePollingChannelAdapter由所提供名称(由输出频道名称选项)在第一页接收()呼叫,而不是在初始化阶段。 它允许“晚绑定”逻辑:目标消息频道从消费者角度看,BEAN 的创建和注册时间稍晚于@InboundChannelAdapter解析阶段。spring-doc.cadn.net.cn

第一个例子要求默认轮询器在应用上下文的其他地方被声明。spring-doc.cadn.net.cn

使用@MessagingGateway注解spring-doc.cadn.net.cn

使用@IntegrationComponentScan注解

标准的Spring框架@ComponentScan注释不会扫描接口以识别刻板印象@Component附注。 为了克服这一限制,允许@MessagingGateway(参见@MessagingGateway注解),我们引入了@IntegrationComponentScan机制。 该注释必须加上@Configuration注释并可定制以定义其扫描选项, 如basePackagesbasePackageClasses. 在这种情况下,所有发现的接口都标注为@MessagingGateway被解析并注册为GatewayProxyFactoryBean实例。 所有其他基于类的组件都由标准解析@ComponentScan.spring-doc.cadn.net.cn

消息元注释

从4.0版本开始,所有消息注释都可以配置为元注释,所有用户自定义消息注释都可以定义相同的属性来覆盖其默认值。 此外,元注释也可以分层配置,如下示例所示:spring-doc.cadn.net.cn

@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 与用户注释的依赖隔离,避免用户类中使用。 如果框架找到一个带有用户注释且带有框架元注释的方法,则视为该方法直接用该框架注释进行注释。spring-doc.cadn.net.cn

注释@Bean方法

从4.0版本开始,你可以在@Bean方法定义@Configuration类,用来生成基于豆子(BEANS)而非方法的消息端点。 它在@Bean定义是“跳出框架”的消息处理器实例(聚合消息处理器,默认消息分裂器,以及其他),转换器实例(JsonToObjectTransformer,ClaimCheckOutTransformer,以及其他),消息源实例(文件阅读消息源,RedisStoreMessageSource,以及其他。 以下示例展示了如何使用消息注释,且@Bean附注:spring-doc.cadn.net.cn

@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 版本引入了对@Bean注释为@InboundChannelAdapter回归java.util.function.Supplier,可以产生POJO或消息. 以下示例展示了如何使用该组合:spring-doc.cadn.net.cn

@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方法也包括(该@MyServiceActivator前面描述的注释可以应用于@Bean定义)。spring-doc.cadn.net.cn

当你在消费者身上使用这些注释时@Bean如果豆子定义返回了适当的消息处理器(根据注释类型),你必须设置属性(例如输出通道,需要回复,次序以及其他方面)。消息处理器 @Bean定义本身。 仅使用以下注释属性:建议链,自动启动,输入通道,阶段轮询者. 其他属性都是给作者用的。
Beans名称通过以下算法生成:
  • 消息处理器 (消息源) @Bean其标准名称来自方法名称或名称属性@Bean. 这就像没有消息注释一样@Bean方法。spring-doc.cadn.net.cn

  • 摘要终点豆名的生成模式如下:[@Bean姓名]。[去大写AnnotationClassShortName]. 例如,SourcePollingChannelAdapter端点控制台来源()前面所示的定义 得到豆子名consoleSource.inboundChannelAdapter. 与 POJO 方法不同,豆子方法名称不包含在端点豆子名称中。 另见端点豆名称spring-doc.cadn.net.cn

  • 如果@Bean不能直接在目标端点中使用(非消息源,摘要回复制作消息处理器摘要消息路由器),分别摘要标准消息处理器工厂豆注册以委托此事@Bean. 这种包裹物的豆子名称由以下模式生成:[@Bean姓名]。[去大写AnnotationClassShortName]。[训导员(或消息来源)].spring-doc.cadn.net.cn

在使用这些注释时@Bean定义,输入通道必须引用声明的豆子。 如果通道尚未在应用上下文中出现,则会自动声明。

在 Java 配置中,你可以使用任何一个配置@Conditional(例如,@Profile) 定义@Bean方法层级因为某些条件原因跳过了豆子注册。 以下示例展示了如何实现:spring-doc.cadn.net.cn

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

结合现有的 Spring 容器逻辑,消息端点 bean(基于@ServiceActivator注释),也未被注册。spring-doc.cadn.net.cn

创建带有注释的桥梁

从4.0版本开始,Java配置提供了@BridgeFrom@BridgeTo @Bean方法注释以标记消息频道豆子@Configuration类。 这些功能实际上是为了完整性,提供了一种方便的机制来声明桥接处理者以及其消息端点配置:spring-doc.cadn.net.cn

@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();
}

你也可以把这些注释当作元注释使用。spring-doc.cadn.net.cn

注释端点的建议

消息映射规则与约定

Spring Integration 实现了一种灵活的功能,可以将消息映射到方法及其参数,无需额外配置,依赖一些默认规则并定义某些约定。 以下章节的例子阐述了规则。spring-doc.cadn.net.cn

示例场景

以下示例展示了一个未注释的参数(对象或原语),它不是地图或者性能具有非空返回类型的对象:spring-doc.cadn.net.cn

public String doSomething(Object o);

输入参数是一个消息有效载荷。 如果参数类型与消息有效载荷不兼容,则尝试使用Spring 3.0提供的转换服务进行转换。 返回值被纳入返回消息的有效载荷。spring-doc.cadn.net.cn

以下示例展示了一个未注释的参数(对象或原元),它不是地图或者性能其中消息返回类型:spring-doc.cadn.net.cn

public Message doSomething(Object o);

输入参数是一个消息有效载荷。 如果参数类型与消息有效载荷不兼容,则尝试使用Spring 3.0提供的转换服务进行转换。 返回值是新构建的消息,发送到下一个目的地。spring-doc.cadn.net.cn

以下示例展示了一个参数,该参数是一个消息(或其子类之一),具有任意对象或原始返回类型:spring-doc.cadn.net.cn

public int doSomething(Message msg);

输入参数本身是消息. 返回值成为消息该数据被送往下一个目的地。spring-doc.cadn.net.cn

以下示例展示了一个单一参数,该参数为消息(或其子类之一)具有消息(或其子类之一)作为返回类型:spring-doc.cadn.net.cn

public Message doSomething(Message msg);

输入参数本身是消息. 返回值是新构建的消息该数据被送往下一个目的地。spring-doc.cadn.net.cn

下例展示了一个类型的参数地图性能其中消息作为返回类型:spring-doc.cadn.net.cn

public Message doSomething(Map m);

这个有点有趣。 虽然一开始看似简单地直接映射到消息头,但通常优先考虑消息有效载荷。 这意味着如果消息有效载荷类型为地图,这个输入参数表示一个消息有效载荷。 然而,如果消息有效载荷不是类型地图转换服务不尝试转换有效载荷,输入参数映射到消息头部。spring-doc.cadn.net.cn

以下示例展示了两个参数,其中一个是任意类型(对象或原元),但不是地图或者性能对象,另一个类型为地图性能类型(无论报税结果如何):spring-doc.cadn.net.cn

public Message doSomething(Map h, <T> t);

该组合包含两个输入参数,其中一个类型为地图. 那个非——地图参数(无论顺序如何)都映射到消息有效载荷和地图性能(无论顺序如何)都映射到消息头部,提供了一种很好的POJO交互方式消息结构。spring-doc.cadn.net.cn

以下示例显示无参数(无论返回如何):spring-doc.cadn.net.cn

public String doSomething();

该消息处理方法的调用基于发送到该处理程序所连接的输入信道的消息。 然而,没有消息数据被映射,因此消息作为事件或触发器来调用处理者。 输出按照前面描述的规则进行映射。spring-doc.cadn.net.cn

以下示例显示无参数且返回为空值:spring-doc.cadn.net.cn

public void soSomething();

这个例子和前面的例子一样,但它不产生输出。spring-doc.cadn.net.cn

基于注释的映射

基于注释的映射是最安全且最不歧义的将消息映射到方法的方法。 以下示例展示了如何显式地将方法映射到报头:spring-doc.cadn.net.cn

public String doSomething(@Payload String s, @Header("someheader") String b)

如你后面所见,如果没有注释,这个签名会导致歧义条件。 然而,通过显式地将第一个参数映射到消息有效载荷,以及对某标题消息头部,我们避免了任何歧义。spring-doc.cadn.net.cn

以下示例与前例几乎相同:spring-doc.cadn.net.cn

public String doSomething(@Payload String s, @RequestParam("something") String b)

@RequestMapping或者任何其他非 Spring Integration 映射注释都无关紧要,因此忽略,第二个参数未映射。 虽然第二个参数可以轻松映射到有效载荷,但实际上只能有一个有效载荷。 因此,注释避免了这种方法的歧义。spring-doc.cadn.net.cn

以下示例展示了另一种类似方法,如果没有注释来澄清意图,这种方法会显得模糊:spring-doc.cadn.net.cn

public String foo(String s, @Header("foo") String b)

唯一的区别是第一个参数隐式映射到消息有效载荷。spring-doc.cadn.net.cn

以下示例展示了另一个签名,如果没有注释,肯定会被视为歧义,因为它有超过两个参数:spring-doc.cadn.net.cn

public String soSomething(@Headers Map m, @Header("something") Map f, @Header("someotherthing") String bar)

这个例子尤其有问题,因为其中两个论证是地图实例。 然而,基于注释的映射可以轻松避免歧义。 在这个例子中,第一个参数映射到所有消息头,而第二和第三个参数映射到名为“something”和“someotherthing”的消息头的值。 有效载荷没有映射到任何参数。spring-doc.cadn.net.cn

复杂情景

以下示例使用多个参数:spring-doc.cadn.net.cn

多个参数会在确定合适的映射时造成很大模糊性。 一般建议是用@Payload,@Header@Headers. 本节示例显示了导致例外情况的模糊条件。spring-doc.cadn.net.cn

public String doSomething(String s, int i)

这两个参数的重量相等。 因此,无法确定哪个是有效载荷。spring-doc.cadn.net.cn

下一个例子展示了类似的问题,但有三个参数:spring-doc.cadn.net.cn

public String foo(String s, Map m, String b)

虽然Map可以轻松映射到消息头部,但无法确定这两个字符串参数的处理方式。spring-doc.cadn.net.cn

以下示例展示了另一种歧义方法:spring-doc.cadn.net.cn

public String foo(Map m, Map f)

虽然有人可能会争论这一点地图可以映射到消息有效载荷,另一个映射到消息头部,我们不能依赖顺序。spring-doc.cadn.net.cn

任何具有多个方法参数且不是的方法签名(地图,<了>)且参数未标注,会导致歧义并触发异常。

接下来的一组示例展示了多种导致歧义的方法。spring-doc.cadn.net.cn

拥有多方法的消息处理程序基于之前(示例中)描述的相同规则进行映射。 不过,有些场景看起来仍然可能让人困惑。spring-doc.cadn.net.cn

以下示例展示了具有合法(可映射且无歧义)签名的多种方法:spring-doc.cadn.net.cn

public class Something {
    public String doSomething(String str, Map m);

    public String doSomething(Map m);
}

(无论这些方法名称相同或不同,都无关紧要。) 这消息可以映射到任一方法。 当消息有效载荷可以映射到 时,会调用第一种方法力量消息头可以映射到m. 第二种方法也可以作为候选方法,仅将消息头映射到m. 更糟糕的是,这两种方法的名字相同。 起初,这看起来可能有些模糊,因为以下配置:spring-doc.cadn.net.cn

<int:service-activator input-channel="input" output-channel="output" method="doSomething">
    <bean class="org.things.Something"/>
</int:service-activator>

之所以有效,是因为映射首先基于有效载荷,其次才考虑其他一切。 换句话说,第一个参数可以映射到有效载荷的方法优先于所有其他方法。spring-doc.cadn.net.cn

现在考虑一个另一个例子,它产生了一个真正模糊的条件:spring-doc.cadn.net.cn

public class Something {
    public String doSomething(String str, Map m);

    public String doSomething(String str);
}

这两种方法都有可以映射到消息有效载荷的签名。 它们的名字也相同。 此类处理方法会触发异常。 然而,如果方法名称不同,你可以用方法属性(见下一个示例)。 以下示例展示了同一示例,但使用了两种不同的方法名称:spring-doc.cadn.net.cn

public class Something {
    public String doSomething(String str, Map m);

    public String doSomethingElse(String str);
}

以下示例展示了如何使用方法属性来决定映射:spring-doc.cadn.net.cn

<int:service-activator input-channel="input" output-channel="output" method="doSomethingElse">
    <bean class="org.bar.Foo"/>
</int:service-activator>

因为该配置显式地映射了做点别的事方法,我们消除了歧义。spring-doc.cadn.net.cn