Overview
In a previous article, the introduction of injecting yourself into a bean, if there are @async and @transaction, if you use @autowire to inject itself, will report a cyclic dependency if you use Beanfactoryaware to inject yourself, Will invalidate the @transaction. For example:
@Service Public classMyServiceImplementsbeanfactoryaware{PrivateMyService Self; //Invalid transaction annotations@Transactional Public voidnotwork () {...} @Async PublicFuture Async () {...} @Override Public voidSetbeanfactory (Beanfactory beanfactory)throwsbeansexception { self= Beanfactory.getbean (MyService.class); }}
Just a brief mention, this article is to explain why the failure.
General situation
The following conditions are required to cause the above situation:
- Annotated with @async and other similar @transaction
- Own class in the Beanfactoryaware, through Beanfactory to get their own
Result: Annotations other than @async take effect, others do not take effect, such as
And the normal agent should be:
Reason
The first thing that comes to mind is that @async annotations may be handled differently than others. In the implementation of Asyncannotationbeanpostprocessor (the specific code is in its parent class abstractadvisingbeanpostprocessor), a problem is found,
Normally, the bean that comes in is already the agent's dynamic proxy class, and when it fails, it comes in really real class, such as:
Then in the analysis of the code, if the actual class, go to 69 rows, the return is true, the @aysnc advisor added to the dynamic truth, and if the actual class, go to 83 rows, will create a proxy class, only the @aysnc advisor to the dynamic agent, What has been done, such as @transaction, will lapse.
Why isn't the proxy class coming in?
In fact, the only difference is beanfactoryaware, whether through the Beanfactory acquired themselves. Then why use Beanfactory to obtain oneself, the subsequent beanpostprocessor is not the agent? If you are familiar with the spring @Transaction loading mechanism, it is known that dynamic proxy creation, such as @transaction, @Retryable annotations, is created in Annotationawareaspectjautoproxycreator. Through debug discovery, after annotationawareaspectjautoproxycreator, our dynamic agent unexpectedly did not add.
Take a look at the implementation in Annotationawareaspectjautoproxycreator, but after he did not generate proxy classes. The reason is that the early exposure of the map has "MyService",
When did he reveal it? is actually in
@Override Public void throws beansexception { self = beanfactory.getbean (myservice. Class);}
So, everything is out, in the instance MyService, triggered by Beanfactoryaware, through Beanfactory.getbean (Myservice.class), the proxy class was created (tips: The current proxy class does not contain @async adivisor), because now spring is actually creating myservice, which is not yet put into the beanfactory. We then trigger a Beanfactory.getbean (Myservice.class) again in this process, causing the agent to be created and returned, and added to the map that was exposed in advance. Cause a series of problems later. It feels a little bit around. Look at the words:
The normal situation should be the following process:
This is the exception.
Summary
Under normal circumstances, use @autowire to inject (if using autowire, the above situation directly throws back the cyclic dependency). Of course, there is a problem, but also can not let go, to know it but also to know its why!
About Spring Annotations @async trigger other annotations to fail