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 thatBeanAfter dependency injection is complete, initialization is performed before the entire container is started. And at this point, we’re callingBeanIf there are AOP annotations configured above, then AOP code will be woven into them. That means that at this pointBeanThe instance is already a proxy object. thenBeanWhen 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 codeBeanPostProcessorImplementation 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 isproxyFactorythegetProxy()Methods. You can tell by the name,proxyFactoryIs to manage variousProxyIn the factory. Follow up and discover that it calls a subclassProxyCreatorSupportthecreateAopProxy()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, namelyJDKProxyCGLib. Let’s look at how Spring uses JDK to generate proxy objectsJdkDynamicAopProxyIn this class, go directly to the relevant code:

InvocationHandlerIs the core of the JDK’s dynamic proxy, which delegates method calls to generated proxy objectsInvocationHandler.invoke()Methods. And from aJdkDynamicAopProxyWe 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:

  1. First get the Interceptor Chain applied to this method.
  2. If there is a notification, the notification is applied and executedJoinPoint; 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,AdvisedCan be applied to JoinPoint or Target classAdvisorIt’s all converted intoMethodInterceptorLet’s take a look at how the resulting interceptor chain works. Actually calledReflectiveMethodInvocationproceedThe 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 interceptorsDefaultAdvisorChainFactorythegetInterceptorsAndDynamicInterceptionAdvice()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 calledDefaultAdvisorAdapterRegistrythegetInterceptors()Get. inDefaultAdvisorAdapterRegistryThe 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 toMethodBeforeAdviceAdapterFor example, look at the concrete implementation:

Spring AOP for implementationadviceSpecific 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