我在网上看到的大多数资源都是通过以下方式声明
MessageChannel
的:
@Bean
MessageChannel myChannel() {
return new MessageChannels.direct().get();
}
似乎
.get()
方法已被弃用,并注明框架将在时间到时自动获取对象。一些较新的示例已声明消息通道 bean 以返回规范:
@Bean
DirectChannelSpec myChannel() {
return new MessageChannels.direct();
}
在大多数情况下仍然可以引用
mychannel()
,因为 IntegrationFlow.from() 允许您传入 Spec 而不是实际通道。但是,在某些情况下,不支持传递规范。我遇到的一种情况是使用 .enrichHeaders
指定错误通道。我只能传入 MessageChannel 本身或消息通道名称作为字符串。
在这种情况下,现在的一般做法是仅使用消息通道的字符串名称吗?或者我应该声明一个仅使用通道构造函数的 bean?
@Bean
MessageChannel certainErrorChannel() {
return new DirectChannel();
}
不使用
Spec
工厂有什么缺点?
当我 10 年前最初设计
MessageChannels
工厂时,它的目的只是作为 Java DSL 配置的流畅 API 内联使用。然后我意识到太多的方法链级别会给代码带来意大利面条式的印象,所以我将该工厂作为公共 API 的所有 ChannelSpec
实现。现在我们可以选择创建通道:通过它们的构造函数或使用这个工厂。在某些情况下,这仍然会引起一些混乱,因为最终用户面临着选择的悖论。感觉你也撞到了。
enrichHeaders()
和它的 errorChannel()
配置确实不一样,什么是 IntegrationFlow.from()
或 channel()
。这两个在配置阶段起作用,因此我们确实可以传递一个ChannelSpec
,框架将为我们配置各自的bean。
errorChannel
的 HeaderEnricher
选项已经与运行时逻辑有关,以将这样的标头添加到消息传递中。因此 Spec
不能在这里使用,因为我们不在这里处理配置阶段。
到处传递频道名称是非常方便的方法。首先:它使流程定义易于阅读。其次,如果通道在配置阶段不退出,它将被创建(如果我们真的谈论配置组件)。通道名称在运行时解析为其 bean。
但是,正如您所看到的,它有一个缺陷,我们需要在运行时从名称解析 bean。特别是如果您谈论
enrichHeaders()
:运行时的每条消息都将针对带有通道名称的标头进行修改。稍后该名称将被解析为 bean。
最有效的方法实际上是对通道 bean 使用普通的 ctor:您拥有对对象的所有控制权,并且不会遭受
MessageChannels
工厂中缺少某些 API 的困扰。您可以使用参数注入到 IntegrationFlow
bean 定义中,并在 DSL 中需要时使用此 MessageChannel
实例。这样就不会创建额外的 bean,并且在运行时也不会产生额外的逻辑。只是更多编码的问题。
一切都是你自己的选择和约定。
注意:建议使用
@Configuration(proxyBeanMethods = false)
并且不要使用彼此的 bean 方法引用:没有代理 - 没有额外的开销。