10年前,当我最初设计MessageChannels
工厂时,它只打算作为Java DSL配置的流畅API内联使用.然后我意识到太多的方法链级会给代码留下意大利面的印象,所以我将该工厂作为公共API的所有ChannelSpec
个实现.现在我们有一些 Select 来创建通道:通过它们的构造器或使用这个工厂.这在某些情况下仍然会造成一些困惑,因为最终用户面临着 Select 的悖论.这感觉就像你也撞到了.
enrichHeaders()
和它的errorChannel()
配置真的不同于IntegrationFlow.from()
或channel()
.这两个在配置阶段有影响,因此我们真的可以传递一个ChannelSpec
,框架将为我们配置各自的Bean.
HeaderEnricher
的errorChannel
选项已经是关于将这样的头添加到消息传递中的运行时逻辑.因此,Spec
不能在这里使用,因为我们在这里不处理配置阶段.
取而代之的是到处传递频道名称是非常方便的方式.首先:它使流定义易于阅读.其次,如果通道在配置阶段没有退出,它将被创建(如果我们真的谈论配置组件).频道名称在运行时被解析为其Bean.
然而,正如你所看到的,它有一个缺陷,我们需要在运行时从名称中解析bean.特别是如果你谈论enrichHeaders()
:每个消息在运行时都将被修改为具有通道名称的头部.稍后这个名字将被解析为bean.
最有效的方法实际上是对通道Bean使用纯ctor:您拥有对对象的所有控制,并且不会受到MessageChannels
工厂中缺少的一些API的影响.您可以将参数注入到IntegrationFlow
Bean定义中,并在DSL中需要的任何时候使用此MessageChannel
实例.这样,在运行时不会创建额外的Bean,也不会产生额外的逻辑.唯一的问题是,更多的编码.
在一切都是你自己的 Select 和惯例中.
注意:建议使用@Configuration(proxyBeanMethods = false)
,并且不要相互使用Bean方法引用:没有代理-没有额外的开销.
编辑:声明带有代理bean方法的IntegrationFlow禁用:
@Bean
IntegrationFlow myFlow(MessageChannel myErrorChannel, MessageChannel out) {
IntegrationFlow.from(...)
.enrichHeaders("errorChannel", myErrorChannel)
.handle(...)
.channel(out)
.get();
}
@Bean
public MessageChannel myErrorChannel { return new DirectChannel(); }
@Bean
public MessageChannel out { return new DirectChannel(); }