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
Executor
in theSimpleApplicationEventMulticaster
instance?
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
SimpleApplicationEventMulticaster
for asynchronous publication of events will make all publication asynchronous, even if undesirable in some circumstances. - Configuring listeners via
@Async @EventListener
allows 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.