【发布时间】:2018-09-22 21:47:00
【问题描述】:
我有一个经过精心设置的用于肥皂呼叫的出站网关 (MarshallingWebServiceOutboundGateway)。我需要从多个流中使用该网关定义。 spring-integration: MessageProducer may only be referenced once 的问题有点类似,但是这个问题是关于 spring 集成协作者正确使用 spring bean 范围原型的。
我有一个单独的配置文件,用于设置网关及其依赖项:
@Bean
public MarshallingWebServiceOutboundGateway myServiceGateway() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan("blah.*");
MarshallingWebServiceOutboundGateway gateway = new MarshallingWebServiceOutboundGateway(
serviceEndpoint, marshaller, messageFactory);
gateway.setMessageSender(messageSender);
gateway.setRequestCallback(messageCallback);
return gateway;
}
这就是我最初尝试从两个不同配置文件中的两个不同流连接出站网关的方式。
在一个配置文件中:
@Bean
public IntegrationFlow flow1() {
MarshallingWebServiceOutboundGateway myServiceGateway = context.getBean("myServiceGateway", MarshallingWebServiceOutboundGateway.class);
return IntegrationFlows
.from(Http.inboundGateway("/res1")
.requestMapping(r -> r.methods(HttpMethod.GET))
.transform(soapRequestTransformer)
.handle(myServiceGateway) // wrong: cannot be same bean
.transform(widgetTransformer)
.get();
}
在单独的配置文件中:
@Bean
public IntegrationFlow flow2() {
MarshallingWebServiceOutboundGateway myServiceGateway = context.getBean("myServiceGateway", MarshallingWebServiceOutboundGateway.class);
return IntegrationFlows
.from(Http.inboundGateway("/res2")
.requestMapping(r -> r.methods(HttpMethod.GET))
.transform(soapRequestTransformer)
.handle(myServiceGateway) // wrong: cannot be same bean
.transform(widgetTransformer)
.handle(servicePojo)
.get();
}
这是一个问题,因为 - 据我了解 - myServiceGateway 不能是同一个实例,因为该实例只有一个出站通道并且不能属于两个不同的流。
在相关问题spring-integration: MessageProducer may only be referenced once 中,@artem-bilan 建议不要在@Bean 方法中创建出站网关,而是使用为每次调用创建新实例的普通方法。
这行得通,但对我来说很不方便。我需要在不同的配置文件中重用来自多个流的出站网关,并且我必须将创建网关的代码复制到每个配置文件中。此外,网关依赖项膨胀了我的配置文件构造函数,使 Sonar 保释。
由于来自IntegrationFlowDefinition.checkReuse() 的错误消息是A reply MessageProducer may only be referenced once (myServiceGateway) - use @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) on @Bean definition.,我想再试一次示波器原型。
所以我尝试让spring集成通过名称从上下文中查找原型网关,希望在flow1和flow2中得到不同的网关实例:
.handle(context.getBean("myServiceGateway",
MarshallingWebServiceOutboundGateway.class))
我用
注释了出站网关@Bean 定义@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
但我可以看到 myServiceGateway() 方法只被调用一次,尽管原型范围,并且应用程序启动仍然失败并显示建议使用原型范围的错误消息 - 实际上很混乱;-)
基于Mystery around Spring Integration and prototype scope我也试过了:
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
应用程序启动,但响应从未到达网关之后的步骤,widgetTransformer。 (更奇怪的是,widgetTransformer 被跳过了:在flow1 中,结果是未转换的网关响应,而在flow2 中,未转换的消息命中了 在 widgetTransformer 之后的步骤,即@987654339 @)。从消息生产者中创建代理似乎不是一个好主意。
我真的很想弄清楚这一点。要求使用原型范围的异常消息是错误的还是我弄错了?如果我需要多个以相同方式设置的此类生产者,如何避免为消息生产者重复 bean 定义?
使用弹簧集成 5.0.9。
【问题讨论】:
标签: spring-integration spring-integration-dsl