# Spring 应用事件支持 ## Spring `ApplicationEvent`支持 Spring 集成提供了对入站和出站`ApplicationEvents`的支持,如底层 Spring 框架所定义的那样。有关 Spring 对事件和侦听器的支持的更多信息,请参见[Spring Reference Manual](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#context-functionality-events)。 你需要在项目中包含此依赖项: Maven ``` org.springframework.integration spring-integration-event 5.5.9 ``` Gradle ``` compile "org.springframework.integration:spring-integration-event:5.5.9" ``` ### 接收 Spring 应用事件 要接收事件并将其发送到通道,你可以定义 Spring Integration 的`ApplicationEventListeningMessageProducer`实例。这个类是 Spring 的`ApplicationListener`接口的实现。默认情况下,它将所有接收到的事件作为 Spring 集成消息传递。要根据事件的类型进行限制,可以使用“eventTypes”属性来配置要接收的事件类型列表。如果接收到的事件有一个`Message`实例作为其“源”,则该`Message`将按原样传递。否则,如果提供了基于 SPEL 的`payloadExpression`,则根据`ApplicationEvent`实例对其进行求值。如果事件的源不是`Message`实例,并且没有提供`payloadExpression`,则`ApplicationEvent`本身将作为有效负载传递。 从版本 4.2 开始,`ApplicationEventListeningMessageProducer`实现了`GenericApplicationListener`,并且可以被配置为不仅接受`ApplicationEvent`类型,还接受用于处理有效负载事件的任何类型(自 Spring Framework4.2 以来也支持这种类型)。当接受的事件是`PayloadApplicationEvent`的实例时,它的`payload`用于发送消息。 为了方便起见,提供了名称空间支持,以配置带有`inbound-channel-adapter`元素的`ApplicationEventListeningMessageProducer`,如下例所示: ``` ``` 在前面的示例中,与“event-types”(可选)属性指定的类型之一相匹配的所有应用程序上下文事件都作为 Spring 集成消息传递到名为“EventChannel”的消息通道。如果下游组件抛出异常,则将包含失败消息和异常的`MessagingException`发送到名为“EvenTerrorChannel”的通道。如果指定了 no`error-channel`,并且下游通道是同步的,则异常将传播给调用方。 使用 Java 配置相同的适配器: ``` @Bean public ApplicationEventListeningMessageProducer eventsAdapter( MessageChannel eventChannel, MessageChannel eventErrorChannel) { ApplicationEventListeningMessageProducer producer = new ApplicationEventListeningMessageProducer(); producer.setEventTypes(example.FooEvent.class, example.BarEvent.class, java.util.Date.class); producer.setOutputChannel(eventChannel); producer.setErrorChannel(eventErrorChannel); return producer; } ``` 使用 Java DSL: ``` @Bean public ApplicationEventListeningMessageProducer eventsAdapter() { ApplicationEventListeningMessageProducer producer = new ApplicationEventListeningMessageProducer(); producer.setEventTypes(example.FooEvent.class, example.BarEvent.class, java.util.Date.class); return producer; } @Bean public IntegrationFlow eventFlow(ApplicationEventListeningMessageProducer eventsAdapter, MessageChannel eventErrorChannel) { return IntegrationFlows.from(eventsAdapter, e -> e.errorChannel(eventErrorChannel)) .handle(...) ... .get(); } ``` ### 发送 Spring 应用程序事件 要发送 Spring `ApplicationEvents`,请创建`ApplicationEventPublishingMessageHandler`的一个实例,并将其注册到一个端点中。`MessageHandler`接口的此实现还实现了 Spring 的`ApplicationEventPublisherAware`接口,因此充当 Spring 集成消息和`ApplicationEvents`之间的桥梁。 为了方便起见,提供了名称空间支持,以配置带有`outbound-channel-adapter`元素的`ApplicationEventPublishingMessageHandler`元素,如下例所示: ``` ``` 如果使用`PollableChannel`(例如`QueueChannel`),还可以提供`poller`元素的子元素。你还可以为该 Poller 提供`task-executor`引用。下面的示例演示了这两个方面: ``` ``` 在前面的示例中,发送到“EventChannel”通道的所有消息都作为`ApplicationEvent`实例发布到在相同的 Spring `ApplicationListener`中注册的任何相关`ApplicationContext`实例。如果消息的有效负载是`ApplicationEvent`,则按原样传递。否则,消息本身被包装在`MessagingEvent`实例中。 从版本 4.2 开始,你可以配置带有`publish-payload`布尔属性的`ApplicationEventPublishingMessageHandler`(``),以按原样发布到应用程序上下文`payload`,而不是将其包装到`MessagingEvent`实例。 要使用 Java 配置来配置适配器: ``` @Bean @ServiceActivator(inputChannel = "eventChannel") public ApplicationEventPublishingMessageHandler eventHandler() { ApplicationEventPublishingMessageHandler handler = new ApplicationEventPublishingMessageHandler(); handler.setPublishPayload(true); return handler; } ``` 使用 Java DSL: ``` @Bean public ApplicationEventPublishingMessageHandler eventHandler() { ApplicationEventPublishingMessageHandler handler = new ApplicationEventPublishingMessageHandler(); handler.setPublishPayload(true); return handler; } @Bean // MessageChannel is "eventsFlow.input" public IntegrationFlow eventsOutFlow(ApplicationEventPublishingMessageHandler eventHandler) { return f -> f.handle(eventHandler); } ```