Overview
In the previous article, it is introduced that if you inject yourself into a bean, if you have @Async and @Transaction, if you inject yourself with @Autowire, you will report a circular dependency. If you inject yourself with BeanFactoryAware, @Transaction will be invalid. For example:
@Servicepublic class MyService implements BeanFactoryAware{ private MyService self; //The transaction annotation is invalid @Transactional public void notWork() { ... } @Async public Future async(){ ... } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { self= beanFactory.getBean(MyService.class); }}I just mentioned it briefly at that time, and this article is to introduce why it failed.
General
The following conditions are required to be met in the above situation:
The result is: except for @Async, the annotation takes effect, and no other ones take effect, as shown in the figure below
The normal proxy should be the following figure:
reason
The first thing that comes to mind is that the processing method of @Async annotation may be different from others. In the implementation of AsyncAnnotationBeanPostProcessor (the specific code is in its parent class AbstractAdvisingBeanPostProcessor), a problem was found,
Under normal circumstances, the bean that comes in is already a dynamic proxy class that is being proxyed, and when it fails, the actual class that comes in is indeed, as shown in the figure below:
Then, after analyzing the code, if it is an actual class, when it reaches line 69, it returns true, and add @Aysnc's Advisor to the dynamic principle. If it is an actual class, when it reaches line 83, it will create a proxy class and only add @Aysnc's advisor to the dynamic proxy, so already @Transaction will be invalid.
Why aren't the agents coming in?
In fact, the only difference is whether you have obtained yourself through BeanFactoryAware. Then why do you use BeanFactory to get yourself, and then you are not a proxy in the subsequent BeanPostProcessor? If you are familiar with the Spring @Transaction loading mechanism, you will know that dynamic proxy creation such as @Transaction and @Retryable annotations is created in AnnotationAwareAspectJAutoProxyCreator. Through debug, we found that after passing through AnnotationAwareAspectJAutoProxyCreator, our dynamic proxy was not added.
Let's take a look at the implementation in AnnotationAwareAspectJAutoProxyCreator, but after it, no proxy class was generated. The reason is that there is "myService" in the Map exposed in advance.
When was he exposed? Actually it's
@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException { self= beanFactory.getBean(MyService.class);}Then, everything came to light. In the instance MyService, BeanFactoryAware was triggered, and a proxy class was created through beanFactory.getBean(MyService.class); (tips: The current proxy class does not contain @Async's Adivisor), because Spring is actually creating the MyService bean and has not been put into the BeanFactory yet. Then we triggered beanFactory.getBean(MyService.class); and after creating a proxy and returning, it was added to the map exposed in advance. This leads to a series of problems that followed. It feels a bit tangled. Talk to the picture:
Normally, the following process should be:
This is the case with abnormal situation
summary
Under normal circumstances, use @Autowire to inject (if Autowire is used, the above situation will directly throw the circular dependency). Of course, if there is a problem, you cannot let it go. You must know the reason and the reason!
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.