AOP is an abbreviation for Aspect Oriented Programming, which means Aspect Oriented Programming. A technique for dynamically adding functionality to a program without modifying the source code, either through precompilation or runtime dynamic proxies. This article will elaborate on the implementation principles of AOP in Spring from a source code perspective.
Several important concepts in AOP
Advice
In AOP terminology, the aspect work is called advice. The advice defines what the aspect is and when to use it. Spring facets can apply five types of notifications:
- Before: Call notification Before the target method is called.
- After notification: The notification is called After the target method completes, regardless of what the output of the method is.
- Post-returning Notification: Notification is called After successful execution of the target method.
- After-throwing: Calls notifications After the target method throws an exception.
- Around advice: Advice wraps a notified method, performing custom behavior before and after the notified method is called.
Join point
A join point is a point at which an aspect can be inserted during application execution. This point can be when a method is called, when an exception is thrown, or even when a field is modified. These points can be used by aspect code to plug into the normal flow of your application and add new behavior.
Pointcut
If the advice defines the “what” and “when” of the aspect, then the pointcut defines the “where.” The definition of the pointcut matches one or more join points that the advice is woven into. We usually specify these pointcuts using explicit class and method names or regular expression definitions that match class and method names.
Aspect
A section is a combination of notification and pointcut. Together, advice and pointcuts define the entirety of an aspect — what it is, when and where it does its job.
Introduction
Imports allow us to add new methods or attributes to existing classes.
Weaving
Weaving is the process of applying a facet to a target object and creating a new proxy object. The section is woven into the target object at the specified join point. There are multiple points that can be woven into the target object’s life cycle.
- Compile time: The aspect is woven in when the target class is compiled. AspectJ’s weaving compiler weaves facets in this way.
- Class loading time: The aspect is woven when the target class is loaded into the JVM. This approach requires a special class loader that enhances the bytecode of the target class before it is introduced into the application. Load-time weaving in AspectJ 5 supports weaving into facets in this way.
- Run-time: Facets are woven in at some point during the application run. Typically, the AOP container dynamically creates a proxy object for the target object when weaving into the cut. String AOP is woven into the facets in this way.
Spring AOP source code analysis
Looking for the entrance
From the analysis in the previous chapter, we know thatBean
After dependency injection is complete, initialization is performed before the entire container is started. And at this point, we’re callingBean
If there are AOP annotations configured above, then AOP code will be woven into them. That means that at this pointBean
The instance is already a proxy object. thenBean
When the instance is proxied, obviously during initialization. Let’s continue with the initialization source code:
As you can see, In wrappedBean = applyBeanPostProcessorsBeforeInitialization (wrappedBean, BeanName) and wrappedBean = applyBeanPostProcessorsAfterInitialization (wrappedBean, beanName); After execution, the wrapped instance wrappedBean is returned. And these two methods respectively called bottom is BeanPostProcessor postProcessBeforeInitialization () and postProcessAfterInitialization () method. Thus, we can infer that AOP must be implemented through some BeanPostProcessor.
Look for a proxy in the name by codeBeanPostProcessor
Implementation class, whose inheritance is as follows:
Can see clearly that all the Proxy classes are derived from an abstract superclass AbstractAutoProxyCreator, the rewrite the postProcessAfterInitialization (), this is the entrance of AOP.
Selecting an agent Policy
Enter thepostProcessAfterInitialization()
Method, we found ourselves moving to a very core methodwrapIfNecessary()
, its source code is as follows:
And as I go through the process, I find that what I end up calling isproxyFactory
thegetProxy()
Methods. You can tell by the name,proxyFactory
Is to manage variousProxy
In the factory. Follow up and discover that it calls a subclassProxyCreatorSupport
thecreateAopProxy()
To get the final proxy object.
DefaultAopProxyFactory createAopProxy = JdkDynamicAopProxy; ObjenesisCglibAopProxy = JdkDynamicAopProxy Use JDK or CGLIB for dynamic proxy.
Calling the proxy method
As we have seen above, Spring provides two ways to generate proxies, namelyJDKProxy
和 CGLib
. Let’s look at how Spring uses JDK to generate proxy objectsJdkDynamicAopProxy
In this class, go directly to the relevant code:
InvocationHandler
Is the core of the JDK’s dynamic proxy, which delegates method calls to generated proxy objectsInvocationHandler.invoke()
Methods. And from aJdkDynamicAopProxy
We can see that this class is also implementedInvocationHandle
, we directly on the source code to seeinvoke()
Methods:
The implementation of the above method is very clear:
- First get the Interceptor Chain applied to this method.
- If there is a notification, the notification is applied and executed
JoinPoint
; If there is no notification, direct reflection is executed.
The key here is how the notification chain is captured and executed, and we’ll take a look at each of them.
How is the notification chain obtained
As you can see from the code above, the notification chain is passedAdvised.getInterceptorsAndDynamicInterceptionAdvice()
Let’s look at the implementation logic of this method:
Get the list of Advisors from the provided configuration instance Config and iterate through them. If the Advisor is a IntroductionAdvisor, determine if the Advisor can be applied to the targetClass targetClass. In the case of the PointcutAdvisor, determine whether the Advisor can be applied to the target Method. The Advisor that meets the criteria is converted into the Interceptor list by AdvisorAdaptor and returned.
How is the notification chain implemented
After the above method is executed,Advised
Can be applied to JoinPoint or Target classAdvisor
It’s all converted intoMethodInterceptor
Let’s take a look at how the resulting interceptor chain works. Actually calledReflectiveMethodInvocation
的proceed
The execution.
Obviously, the main purpose of the above method is to implement chain calls, but what is done in the interceptor and how the notification is triggered is back to the interceptor chain code.
Trigger notifications
We talked about the chain of interceptorsDefaultAdvisorChainFactory
thegetInterceptorsAndDynamicInterceptionAdvice()
Method. In this approach, there is an adapter and registration process, and Spring adds its handling of AOP implementations by configuring Spring to pre-design interceptors.
All interceptors are calledDefaultAdvisorAdapterRegistry
thegetInterceptors()
Get. inDefaultAdvisorAdapterRegistry
The various notification adapters are pre-registered in the constructor of. It is the implementation of these adapters that provides Spring AOP with weaving capabilities. The following toMethodBeforeAdviceAdapter
For example, look at the concrete implementation:
Spring AOP for implementationadvice
Specific interceptors are designed to encapsulate these functions. For example, the example above usesMethodBeforeAdviceInterceptor
, the source code is as follows:
As you can see, for MethodBeforeAdviceInterceptor, when executing the blocker will first invoke the notification before () method, and then continue with the back of the interceptor, other interceptor principle is similar. In this way, all notifications applied to the method are executed once.
Original is not easy, feel that the article is written well small partners, a praise 👍 to encourage it ~
Welcome to my open source project: a lightweight HTTP invocation framework for SpringBoot