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 the SimpleApplicationEventMulticaster 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.