The pit of spring AOP annotation invalidation and JDK dynamic proxy

@Annotations such as transactional @ async do not work

Many people have encountered the situation that annotations do not work when using @ transactional, @ async and other annotations in spring before.

Why did this happen? Because the functions of these annotations are actually implemented by spring AOP, and its implementation principle is implemented through proxy.

JDK dynamic agent

Take a simple example to understand the basic principle of JDK dynamic agent:

The above example should be able to clearly explain the principle of JDK dynamic agent. It uses reflection mechanism to generate an anonymous class that implements the proxy interface. It calls InvokeHandler before invoking specific methods. When we call a method through a proxy class object, we will actually call its invoke method first, and then call the original method. In this way, we can add processing logic before and after the original method logic.

Another dynamic proxy method of spring is cglib dynamic proxy. It loads the class file of the proxy object class and generates subclasses by modifying its bytecode. Although the processing methods are different, the ideas of agents are the same.

If the proxy target object implements the interface, spring will use JDK dynamic proxy by default. All interfaces implemented by this target type will be proxied. If the target object does not implement any interfaces, a cglib proxy is created.

Invalidation and solution of spring AOP annotation

Based on the above analysis of the principle of dynamic agent, let's look at the following two common problems:

In the same class, method a calls method B (method B is annotated), and the annotation is invalid

For all spring AOP annotations, if spring finds such annotations when scanning beans, it will dynamically construct a proxy object.

If you want to directly call the annotated a method through the object of class X, this annotation is valid. Because at this time, spring will judge that there are AOP annotations on the method you are going to call, so it will use the proxy object of class X to call method a.

However, assuming that method a in class X will call annotated method B, and you still want to call method a through class X object, the annotation on Method B is invalid. At this time, spring judges that the a you call has no annotation, so it still uses the original object rather than the proxy object. Next, when a calls B again, the annotation of B method in the original object is of course invalid.

resolvent:

Of course, the simplest way is to make methods a and B independent, and call method B directly through the object of class X.

But most of the time, it may not be good to write our logic in this way, so there is another way: find a way to get the proxy object manually.

Aopcontext class has a currentproxy () method, which can directly get the proxy object of the current class. The above example can be solved as follows:

The @ Autowired object used in the AOP annotation method is null

In previous use, when using other injected objects in annotated methods, it was found that the object was not injected and was null.

Finally, it is found that the reason for this is that the method is private. Because whether spring uses JDK dynamic proxy or cglib dynamic proxy, one is for the class that implements the interface, and the other is implemented through subclasses. Whether it is an interface or a parent class, it is obvious that private methods cannot appear, otherwise the child class or implementation class cannot be overridden.

If the method is private, this method cannot be found during the proxy process, which causes problems in the creation of proxy objects and some objects are not injected.

So if the method needs to use AOP annotation, set it as a non private method.

The above is the whole content of this article. I hope it will be helpful to your study, and I hope you can support programming tips.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>