I got a class that sends out an application event. The receiver must not miss this event, so the sender is dependent on the receiver.
@Service
@DependsOn("receiver")
class Sender {
...
@PostConstruct
public void init(){
applicationEventPublisher.publishEvent(new MyEvent());
}
}
@Service
class Receiver {
...
@EventListener
public void onEvent(MyEvent event) {
System.out.println("Event catched");
}
}
In debugging mode you are able to see that Sender
is initialised after Receiver
, which should result in the Receiver always catching the event of the Sender - but it isn't.
In fact there seems to be a delay between initialising the Receiver and the point it is ready to receive events. If I delay publishing the event in the Sender by a few milliseconds, the receiver catches it as expected.
So it seems like the @DependsOn
doesn't make it entirely sure that the Seceiver is fully initialised before the Sender, which is the exact opposite of what is documented.
How to accomplish that the receiver catches the event without using any ugly delays?
As @M. Deinum suggested, the issue of your problem your are facing is that the application context is not ready at that point to listen to events.
Events fired can be handeled after the BeanFactoryPostProcessor( DefaultListableBeanFactory.preInstantiateSingletons() ) finished. Your postConstruct annotation gets invoked before the BeanFactoryPostProcessor is invoked and this caauses the loss of event handling.(reference spring bean lifecycle )
As a solution your bean could fire the event when the applicationContext is starting ( ContextRefreshedEvent )
@Service
class Sender {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@EventListener
public void applicationStarted(ContextRefreshedEvent event) {
applicationEventPublisher.publishEvent(new MyEvent());
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.