spring-projects / spring-boot

Spring Boot
https://spring.io/projects/spring-boot
Apache License 2.0
74.57k stars 40.55k forks source link

@Async annotations are not working with AdviceMode.ASPECTJ and lazy-initialization=true #39416

Closed kicktipp closed 6 months ago

kicktipp commented 7 months ago

This project reproduces the problem:

https://github.com/kicktipp/lazyasync

The included test does time out as @Async is not working correctly with AdviceMode.ASPECTJ and lazy-initialization=true .

@Configuration
@EnableAsync(mode = AdviceMode.ASPECTJ)
public class AsyncConfig {
}

This works fine usually. To speed up our development server we added this recently

spring.main.lazy-initialization=true

With lazy-initialization set to true, the ThreadPoolTaskExecutor is not configured, therefore all @Async methods are called synchronously which can lead to subtle bugs with @Transactional annotations which are difficult to understand in development mode.

I don't know if you call it a bug. But at least its a pitfall for developers.

wilkinsona commented 6 months ago

Thanks very much for the sample. It made reproducing the problem straightforward. The problem is that the aspect that honours @Async is lazy and isn't applied. You can work around this by excluding it from lazy initialization:

@Bean
static LazyInitializationExcludeFilter eagerAnnotationAsyncWithAspectJ() {
    return LazyInitializationExcludeFilter.forBeanTypes(AnnotationAsyncExecutionAspect.class);
}

We don't have any auto-configuration for @EnableAsync so there's no immediately obvious place for us to put this exclude filter in Boot. Hopefully the above work around will help for now. We'll discuss this as a team to see if we can agree on somewhere to configure it in Boot itself.

wilkinsona commented 6 months ago

We're going to make a change in 3.3 so that all infrastructure beans are excluded from lazy initialization by default (#39831). In the meantime, the filter-based workaround above should be used. Thanks for bringing this to our attention.