控制总线
正如 《企业集成模式》 (EIP) 一书中所述,控制总线背后的理念是,用于监控和管理框架内组件的消息系统可以与用于“应用层”消息传递的系统相同。在 Spring Integration 中,我们在上述适配器的基础上进行构建,以便您可以通过发送消息来调用暴露的操作。
由于控制总线足够强大,可以更改系统状态,因此建议保护其消息接收(参见 SecurityContextChannelInterceptor )并仅将控制总线管理(消息源)暴露到 DMZ 区。 |
以下示例展示了如何使用 XML 配置控制总线
<int:control-bus input-channel="operationChannel"/>
控制总线有一个输入通道,可用于调用应用程序上下文中的 bean 上的操作。它还具有服务激活端点的所有常见属性。例如,如果操作结果有返回值并且您想将其发送到下游通道,则可以指定一个输出通道。
控制总线将输入通道上的消息作为托管操作运行,格式为简单的字符串,例如 beanName.methodName
。目标方法参数的参数必须在 IntegrationMessageHeaderAccessor.CONTROL_BUS_ARGUMENTS
头中作为列表提供。要调用的 bean 和方法从 ControlBusCommandRegistry
基础架构 bean 解析。默认情况下,ControlBusCommandRegistry
按需注册命令:其 eagerInitialization
标志可以通过 @EnableIntegrationManagement(loadControlBusCommands = "true")
开启。
控制总线的功能类似于 JMX,因此方法符合命令资格必须满足以下要求
-
使用
@ManagedAttribute
或@ManagedOperation
注解的方法; -
Spring 的
Lifecycle
接口(及其自 5.2 版本以来的Pausable
扩展); -
用于配置 Spring 的几种
TaskExecutor
和TaskScheduler
实现的方法。
确保您自己的方法可供控制总线使用的最简单方法是使用 @ManagedAttribute
或 @ManagedOperation
注解。由于这些注解也用于将方法暴露给 JMX MBean 注册表,因此它们提供了一个方便的副产品:通常,您希望暴露给控制总线的操作类型也适合通过 JMX 暴露)。更多信息请参阅 ControlBusCommandRegistry
和 ControlBusMethodFilter
的 Javadoc 文档。
要在 Spring Bean 上执行方法,客户端可以按如下方式向操作通道发送消息
Message<?> operation = MessageBuilder.withPayload("myServiceBean.shutdown").build();
operationChannel.send(operation);
如果要调用的目标方法带有参数(例如 ThreadPoolTaskExecutor.setMaxPoolSize(int maxPoolSize)
),这些值必须作为 IntegrationMessageHeaderAccessor.CONTROL_BUS_ARGUMENTS
头提供
Message<?> operation =
MessageBuilder.withPayload("myTaskExecutor.setMaxPoolSize")
.setHeader(IntegrationMessageHeaderAccessor.CONTROL_BUS_ARGUMENTS, List.of(10))
.build();
operationChannel.send(operation);
您可以将这些命令视为 JDBC 中的 PreparedStatement
实例,带有参数绑定。参数的类型必须与方法参数的类型匹配。它们用作根据 Java 方法重载特性选择要调用的方法的附加标准。例如,组件
@ManagedResource
class TestManagementComponent {
@ManagedOperation
public void operation() {
}
@ManagedOperation(description = "The overloaded operation with int argument")
public void operation(int input) {
}
@ManagedOperation(description = "The overloaded operation with two arguments")
public void operation(int input1, String input2) {
}
@ManagedOperation
public int operation2() {
return 123;
}
}
将暴露 3 个名为 operation
的命令。当我们调用 testManagementComponent.operation
命令时,我们应该为 IntegrationMessageHeaderAccessor.CONTROL_BUS_ARGUMENTS
头选择一个适当的值列表,以便让 ControlBusCommandRegistry
过滤出 bean 上的目标方法。
使用 Java 注解,您可以按如下方式配置控制总线
@Bean
@ServiceActivator(inputChannel = "operationChannel")
public ControlBusFactoryBean controlBus() {
return new ControlBusFactoryBean();
}
类似地,您可以按如下方式配置 Java DSL 流定义
@Bean
public IntegrationFlow controlBusFlow() {
return IntegrationFlow.from("controlBus")
.controlBus()
.get();
}
如果您更喜欢使用带有自动 DirectChannel
创建的 Lambda 表达式,可以按如下方式创建控制总线
@Bean
public IntegrationFlow controlBus() {
return IntegrationFlowDefinition::controlBus;
}
在这种情况下,通道被命名为 controlBus.input
。
另请参阅控制总线 REST 控制器,了解如何通过 HTTP 暴露控制总线管理。