我在@Configuration类中使用Spring Boot和Spring Integration Java DSL。其中一个流程是使用带有MessageStore的DelayHandler,通过.delay(String groupId,String expression,Consumer endpointConfigurer):
@Bean
public IntegrationFlow errorFlow() {
return IntegrationFlows.from(errorChannel())
...
.delay(...)
...
.get();
}
我希望利用DelayHandler的reschedulePersistedMessages()功能,但我发现调用它的onApplicationEvent(ContextRefreshedEvent事件)实际上从未被调用过(?)
我不确定,但我怀疑这是因为DelayHandler未注册为Bean,因此AbstractApplicationContext中的registerListeners()无法自动注册DelayHandler(并通过注册非Bean侦听器) ApplicationHventMulticaster.addApplicationListener(ApplicationListener侦听器)没有为DelayHandler完成。
目前,我正在使用一种相当丑陋的解决方法来注册我自己的侦听器Bean,我将注入集成流Bean,然后在找到DelayHandler后手动调用onApplicationEvent():
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
Set<Object> integrationComponents = errorFlow.getIntegrationComponents();
for (Object component : integrationComponents) {
if (component instanceof DelayerEndpointSpec) {
Tuple2<ConsumerEndpointFactoryBean, DelayHandler> tuple2 = ((DelayerEndpointSpec) component).get();
tuple2.getT2().onApplicationEvent(event);
return;
}
}
}
答案 0 :(得分:0)
嗯,是的。该测试用例证实了这个问题:
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class DelayerTests {
private static MessageGroupStore messageGroupStore = new SimpleMessageStore();
private static String GROUP_ID = "testGroup";
@BeforeClass
public static void setup() {
messageGroupStore.addMessageToGroup(GROUP_ID, new GenericMessage<>("foo"));
}
@Autowired
private PollableChannel results;
@Test
public void testDelayRescheduling() {
Message<?> receive = this.results.receive(10000);
assertNotNull(receive);
assertEquals("foo", receive.getPayload());
assertEquals(1, messageGroupStore.getMessageGroupCount());
assertEquals(0, messageGroupStore.getMessageCountForAllMessageGroups());
}
@Configuration
@EnableIntegration
public static class ContextConfiguration {
@Bean
public IntegrationFlow delayFlow() {
return flow ->
flow.delay(GROUP_ID, (String) null,
e -> e.messageStore(messageGroupStore)
.id("delayer"))
.channel(c -> c.queue("results"));
}
}
}
我们走了:documentation here。
作为解决方法,我们可以在@Configuration
:
@Autowired
private ApplicationEventMulticaster multicaster;
@PostConstruct
public void setup() {
this.multicaster.addApplicationListenerBean("delayer.handler");
}
注意beanName
进行注册。这正是我们的流定义中的.id("delayer")
加上.handler
bean定义的DelayHandler
后缀。