initApplicationEventMulticaster() in AbstractApplicationContext creates a new SimpleApplicationEventMulticaster instance and registers it in the container, but the Executor in it is always null because there is no autowiring for it.
Code as below:
https://github.com/spring-projects/spring-framework/blob/f60bec986f9892c6f2f275a133f943a7bc7f490f/spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java#L135-L146
So, when it runs it always steps into the else clause. I would like to ask if I want to invoke listener async, must I use @Async?
Although @Async can work because of dynamic proxy technique.
Or, must I manually set an async Executor in the SimpleApplicationEventMulticaster instance?
I feel puzzled for the code above.
Best Regards
Comment From: sbrannen
Or, must I manually set an async
Executorin theSimpleApplicationEventMulticasterinstance?
If you want to configure the ApplicationEventMulticaster used by the ApplicationContext, you must register a bean of type ApplicationEventMulticaster named applicationEventMulticaster in the context.
Thus to change the Executor used by SimpleApplicationEventMulticaster you would need to register a bean of type SimpleApplicationEventMulticaster named applicationEventMulticaster and configure its Executor.
Although this is partially documented in the class-level Javadoc for AbstractApplicationContext, we will improve the documentation in the Javadoc and reference manual.
Comment From: YJFinBJ
Thanks for your reply. But why not support autowire Executor while initApplicationEventMulticaster
SimpleApplicationEventMulticaster applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
applicationEventMulticaster.setTaskExecutor(taskExecutor)
this.applicationEventMulticaster = applicationEventMulticaster;
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
The taskExecutor can be autowired in spring context as default or self declaration. this way seems much easier to use for most users , in this way, I must not need to reigster a bean of type SimpleApplicationEventMulticaster named applicationEventMulticaster in spring context
Best Regards
Comment From: sbrannen
Hi @YJFinBJ,
I don't think it is very common for people to customize the ApplicationEventMulticaster, and in light of that I don't think we will be seeking to make it any easier than it currently is.
I was merely explaining how one could do that.
I would like to ask if I want to invoke listener async, must I use
@Async?
Having re-read your initial questions, yes, I think configuring individual listeners explicitly as @Async would likely be a better choice. See the Asynchronous Listeners section of the reference manual for details.
Rationale:
- Configuring
SimpleApplicationEventMulticasterfor asynchronous publication of events will make all publication asynchronous, even if undesirable in some circumstances. - Configuring listeners via
@Async @EventListenerallows you to selectively decide which listeners should be asynchronous.
In other words, it's a choice between global asynchronous publication vs. selective asynchronous consumption.
In any case, we can still improve the documentation for configuring the ApplicationEventMulticaster.
Comment From: YJFinBJ
Hi @sbrannen ,
I agree with your opinion for @Async usage because it's more flexible. I just confuse about the code, since define a executor in SimpleApplicationEventMulticaster that most people use, why not make executor in it can be autowired by user on their demand , for example, I indeed want a global asynchronous publication,hope to adopt
Best Regards
Comment From: jhoeller
I've added some explicit hints for setting up a custom "applicationEventMulticaster" bean definition to the reference documentation, typically for asynchronous event processing by default and/or for custom handling of listener exceptions.
At Spring Framework level, TaskExecutor configuration is always explicit. Specific features such as @Async may pick up an executor bean from the context since they are inherently based on asynchronous execution, whereas all common facilities need to be explicitly configured with a TaskExecutor if a switch from the default synchronous mode is desired. For event processing, such a switch changes the default semantics in terms of guaranteed completion when the method returns (and in terms of thread-local visibility), so this will have to remain explicit. And as mentioned above, individual listeners can always opt into asynchronous execution through an @Async marker anyway, choosing the execution semantics per listener.