Today’s sharing started, please give us more advice ~
It is well known that Spring AOP makes our AOP development work much easier. Today we reveal the basic principle and implementation of Spring AOP!
AOP aspect programming: mainly through the aspect class to improve the reuse of code, reduce the coupling of business code, so as to improve the development efficiency. The main functions are: logging, performance statistics, security control, transaction handling, exception handling and so on.
AOP implementation principle: AOP is implemented by cGLIb’s dynamic proxy.
-
JDK dynamic proxy: Use reflection to generate an anonymous class that implements the proxy interface and calls InvokeHandler to handle it before invoking the specific method.
-
Cglib dynamic proxy: Load the class file of the proxy object class and modify its bytecode generation subclasses using ASM bytecode technology.
-
Difference: JDK dynamic proxies can only generate proxies for classes that implement interfaces, not for classes. CGLIB implements proxying for classes, essentially generating a subclass of a specified class that overrides its methods. Because it is inherited, it is best not to declare the class or method final, which prevents inheritance and polymorphism.
use
To analyze the underlying principles of Spring AOP, you need to first use it. Create a normal Maven WebApp project with spring-Context dependencies, version 5.1.1RELEASE.
I then used AspectJ as a syntactic implementation of AOP, integrating it with Spring.
Next I’ll simulate the use of Spring AOP in full form of annotations, creating a configuration class to scan packages and turning on aspectJ’s automatic proxy support.
Then create a new interface and its implementation class:
Create section:
Create test methods:
Execute the method and you can see the print query… I printed before———-
If you know a little about Spring AOP, you will know that spring implements aop using dynamic proxies and bytecode techniques, namely JDK dynamic proxies and Cglib dynamic proxies. How spring created the proxy object, and when the proxy object, let’s explore the source code, to uncover the mystery.
Source code analysis
First, let’s look beyond the appearance to the essence. I’ll put the breakpoint on the last line of the test method. Let’s look at the DAO object at this point.
Then we will go to find when the dao object into a dynamic proxy objects, since at the time of the last line of object has become a proxy objects, so we guess is naturally in a code position on the spring performed to create a proxy object operation, we move the breakpoint to a line, the debug.
This line of code I see method name should be useful code, method meaning should be spring processing bean, follow in to see.
After executing getBeanNamesForType(requiredType), the idea variable is displayed, and the name is IndexDao.
The next thing I need to do is go to the code block where Length ==1, and then I debug it again, which is a getBean method.
There are other beans in the Spring container that need to be created without a name, so I used a conditional breakpoint here. The breakpoint will only be entered when beanName equals indexDao, but when I finished running the line F8, something unexpected happened.
Surprisingly, after the getSingleton line, the proxy object is created, so you need to debug into this line to see it.
But I only see the get method here, so when did these beans go into singletonObjects? Let me find out.
In DefaultSingletonBeanRegistry registry, I found singletonObjects put method, this time on behalf of the bean is to be put into the map, I then conditional breakpoints in this line of code, and then we come to it call chain, Find out when the addSingleton method is executed. From this point I already know that the breakpoint on the penultimate line of the test method is not correct. The proxy object is actually generated before the getBean.
On the createBean method, I also add a conditional breakpoint, and debug enters.
Next I debug into the doCreateBean method
Debug follows the initializeBean method, the conditional breakpoint is on the two initializeBean methods, and I have a vague idea that the proxy object is generated from these methods. We’ll see.
After applyBeanPostProcessorsBeforeInitialization method, this time we see warppedBean or indexDao, did not produce a proxy object.
I guess in the next post-processor, the proxy object will be created and I debug it.
Seeing this processor, IT suddenly became clear to me that it should be the proxy object generated by the processing of this processor. I finished running this code to verify my conjecture.
You can see that my guess is proven correct, and after running the post-processor, the proxy object is created. At this point we know where the proxy object comes from, but we still don’t know how the proxy object is created. At this point we need to debug to look inside the processor.
So I got inside the wrapIfNecessary method again
We see there is an if statement, when the config isOptimize and isProxyTargetClass hasNoUserSuppliedProxyInterfaces three judgment conditions as long as there is a meet, The default value of the two Boolean variables in config is false, and the proxied object implements the interface. Therefore, Spring will choose the IMPLEMENTATION form of JDK dynamic proxy to complete the dynamic proxy.
Of course, we can also manually configure the config value in this case to have Spring select Cglib as the dynamic proxy implementation, as shown later.
To demonstrate how to modify config to let Spring select Cglib as the dynamic proxy implementation with the interface, it is very simple to configure the class annotation with proxyTargetClass=true.
@EnableAspectJAutoProxy(proxyTargetClass = true)
conclusion
I conclude with a call chain diagram for the Spring AOP implementation
Today’s share has ended, please forgive and give advice!