I'm using java config with @ComponentScan
in order to initialize my beans
and @EnableAspectJAutoProxy(proxyTargetClass=true)
to use cglib proxies.
In this project we have a lots of generated services autowired between them using @Autowired
. It works pretty well.
But, for some of these services I've added @Async
(I've also added @EnableAsync(proxyTargetClass = true)
on my @Configuration
class).
After that, I'm getting:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'ConversationUserLocalService': Bean with name 'ConversationUserLocalService' has been injected into other beans [ConversationUserHistoryLocalService] i
n its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'a
llowEagerInit' flag turned off, for example.
I guess this is because Spring is injecting the service with @Async
method BEFORE AOP creates the proxy.
Could this be the problem?
How I should fix it?
In order to try to clarify my problem, let's say I have:
@Service A, B & C;
A has autowired B & C, B has autowired A & C, C has autowired A & B;
C has a method marked as @Async.
When Spring initialize applicationContext, it tries to initialize A, but needs B & C, so it initializes them. But after all, AOP tries to make a proxy of C (because @Async) and then it detects that autowired C into B and A is not the same as proxy of C so it fails.
I hope this can explain a little more what is happening.
AsyncConfigurer configuration classes get initialized early in the application context bootstrap. If you need any dependencies on other beans there, make sure to declare them @Lazy
as far as possible in order to let them go through other post-processors as well.
Reference JavaDoc: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableAsync.html