Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document how to configure the ApplicationEventMulticaster used by the ApplicationContext #29996

Closed
YJFinBJ opened this issue Feb 20, 2023 · 5 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: documentation A documentation task
Milestone

Comments

@YJFinBJ
Copy link

YJFinBJ commented Feb 20, 2023

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:

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}

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

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Feb 20, 2023
@rstoyanchev rstoyanchev added the in: core Issues in core modules (aop, beans, core, context, expression) label Feb 24, 2023
@sbrannen sbrannen changed the title SimpleApplicationEventMulticaster cannot set exector in spring event SimpleApplicationEventMulticaster cannot set Executor in application event Feb 24, 2023
@sbrannen sbrannen self-assigned this Feb 24, 2023
@sbrannen sbrannen added type: documentation A documentation task and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Feb 26, 2023
@sbrannen sbrannen added this to the 6.0.6 milestone Feb 26, 2023
@sbrannen sbrannen changed the title SimpleApplicationEventMulticaster cannot set Executor in application event Document how to set Executor in SimpleApplicationEventMulticaster Feb 28, 2023
@sbrannen sbrannen modified the milestones: 6.0.6, 6.0.7 Mar 2, 2023
@sbrannen
Copy link
Member

sbrannen commented Mar 3, 2023

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.

@YJFinBJ
Copy link
Author

YJFinBJ commented Mar 6, 2023

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

@sbrannen
Copy link
Member

sbrannen commented Mar 8, 2023

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.

@sbrannen sbrannen changed the title Document how to set Executor in SimpleApplicationEventMulticaster Document how to configure ApplicationEventMulticaster used by the ApplicationContext Mar 8, 2023
@sbrannen sbrannen changed the title Document how to configure ApplicationEventMulticaster used by the ApplicationContext Document how to configure the ApplicationEventMulticaster used by the ApplicationContext Mar 8, 2023
@YJFinBJ
Copy link
Author

YJFinBJ commented Mar 10, 2023

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

@sbrannen sbrannen modified the milestones: 6.0.7, 6.0.8 Mar 17, 2023
@sbrannen sbrannen modified the milestones: 6.0.8, 6.0.9 Apr 4, 2023
@snicoll snicoll modified the milestones: 6.0.9, 6.0.x Apr 7, 2023
@sbrannen sbrannen modified the milestones: 6.0.x, 6.1.x Jul 4, 2023
@jhoeller jhoeller assigned jhoeller and unassigned sbrannen Aug 18, 2023
@jhoeller jhoeller modified the milestones: 6.1.x, 6.0.12 Aug 18, 2023
@jhoeller
Copy link
Contributor

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: documentation A documentation task
Projects
None yet
Development

No branches or pull requests

6 participants