Spring AOP implementation of the underlying source code parsing

Simple proxy implementation:

Interface PUserServiceInterface

public interface PUserServiceInterface {
   public void test(a);
}
Copy the code

The implementation class PUserService

public class PUserService implements PUserServiceInterface{ @Override public void test() { System.out.println("test"); }}Copy the code

The test class

public class JdkProxyTest {
    public static void main(String[] args) {
        // 1. Target object
        PUserService userService = new PUserService();

        PUserServiceInterface proxyInterface =
            (PUserServiceInterface) Proxy.newProxyInstance(PUserService.class.getClassLoader(), PUserService.class.getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                System.out.println("Logical agent");
                Object result = method.invoke(userService, args);
                return null; }}); proxyInterface.test(); }}Copy the code

1. ProxyFactory ProxyFactory

public class PTest {
    public static void main(String[] args) {
        // 1. Establish agent factory
        ProxyFactory factory = new ProxyFactory();
        // 2. Set the proxy target
        factory.setTarget(new PUserService());
        // 3. Add proxy logic, here white Euclidean
        factory.addAdvice(new AfterReturningAdvice() {
            @Override
            public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
                System.out.println(method.getName()+"After method return"); }});// 4. Generate proxy objectsPUserServiceInterface userServiceInterface = (PUserServiceInterface)factory.getProxy(); userServiceInterface.test(); }}Copy the code

Advice: proxy logic

PointCut: point of tangency

Advisor=Advice+PointCut

Source code implementation:

  1. new ProxyFactory(); It is straightforward to construct a ProxyFactory object

  2. SetTarget (new PUserService ());

    public void setTarget(Object target) {
       setTargetSource(new SingletonTargetSource(target));
    }
    Copy the code

    Encapsulates the PUserService object

    TargetSource has two encapsulation options

    factory.setTargetClass(PUserService.class);
    
    public void setTargetClass(@NullableClass<? > targetClass) {
        this.targetSource = EmptyTargetSource.forClass(targetClass);
    }
    Copy the code
    1. SingletonTargetSource: Target has a value
    2. EmptyTargetSource: Target has no value
  3. (PUserServiceInterface)factory.getProxy(); Generating proxy objects

    public Object getProxy(a) {
       return createAopProxy().getProxy();
    }
    Copy the code
    1. CreateAopProxy () selects which dynamic proxy to use, cglib or JDK implementation

      public class DefaultAopProxyFactory implements AopProxyFactory.Serializable {
         When does Spring use Cglib and when does it use JDK dynamic proxies
         // If the targetClass is an interface, JDK dynamic proxies will be used
         // By default (optimize is false, isProxyTargetClass is false), ProxyFactory also uses JDK dynamic proxies when adding interfaces
         @Override
         public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
            //
            if(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<? > targetClass = config.getTargetClass();if (targetClass == null) {
                  throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
               }
                // If the target interface is to use JDK dynamic proxies
               if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                  return new JdkDynamicAopProxy(config);
               }
               return new ObjenesisCglibAopProxy(config);
            }
            else {
               return newJdkDynamicAopProxy(config); }}Copy the code
      1. HasNoUserSuppliedProxyInterfaces (config) to determine whether to manually add the interface, added manually, returns false, otherwise returns true

        private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) { Class<? >[] ifcs = config.getProxiedInterfaces();return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0))); }Copy the code

        We can configure this to tell Spring that we want to use the JDK dynamic proxy

        factory.addInterface(PUserService.class); // indicates that we use the JDK dynamic proxy
        Copy the code
    2. JdkDynamicAopProxy(config) implements dynamic proxy

      @Override
      public Object getProxy(@Nullable ClassLoader classLoader) {
         if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
         }
         // Get the interface to be implemented to generate the proxy objectClass<? >[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
         // Check whether any of these interfaces define equals and hashCode methods
         findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
         // Generate proxy objects for the specified interface, including the user-added interface and SpringProxy, Advised, and DecoratingProxy
         // So the generated proxy object can be cast to any interface type
         return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
      }
      Copy the code
      1. completeProxiedInterfaces(this.advised, true)

        staticClass<? >[] completeProxiedInterfaces(AdvisedSupport advised,booleandecoratingProxy) { Class<? >[] specifiedInterfaces = advised.getProxiedInterfaces();// If no interface is specified in ProxyFactory, check whether targetClass is an interface, and if so, add the interface
            if (specifiedInterfaces.length == 0) {
                // No user-specified interfaces: check whether target class is an interface.Class<? > targetClass = advised.getTargetClass();if(targetClass ! =null) {
                    if (targetClass.isInterface()) {
                        advised.setInterfaces(targetClass);
                    }
                    else if(Proxy.isProxyClass(targetClass)) { advised.setInterfaces(targetClass.getInterfaces()); } specifiedInterfaces = advised.getProxiedInterfaces(); }}// In addition to the user-added interface, Spring also adds several default interfaces SpringProxy, Advised, DecoratingProxy
            booleanaddSpringProxy = ! advised.isInterfaceProxied(SpringProxy.class);booleanaddAdvised = ! advised.isOpaque() && ! advised.isInterfaceProxied(Advised.class);booleanaddDecoratingProxy = (decoratingProxy && ! advised.isInterfaceProxied(DecoratingProxy.class)); .return proxiedInterfaces;
        }
        Copy the code
    3. The callback executes the invoke method:

      @Override
      @Nullable
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          Object oldProxy = null;
          boolean setProxyContext = false;
      
          TargetSource targetSource = this.advised.targetSource;
          Object target = null; .// advised is ProxyFactory
              if (this.advised.exposeProxy) {
                  // Make invocation available if necessary.
                  oldProxy = AopContext.setCurrentProxy(proxy);
                  setProxyContext = true;
              }
      
              // Get as late as possible to minimize the time we "own" the target,
              // in case it comes from a pool.target = targetSource.getTarget(); Class<? > targetClass = (target ! =null ? target.getClass() : null);
      
              // Get the interception chain for this method.
              // Get the interceptor chain based on the current method
              List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
      
              // Check whether we have any advice. If we don't, we can fallback on direct
              // reflective invocation of the target, and avoid creating a MethodInvocation.
              if (chain.isEmpty()) {
                  // We can skip creating a MethodInvocation: just invoke the target directly
                  // Note that the final invoker must be an InvokerInterceptor so we know it does
                  // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
                  Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                  retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
              }
              else {
                  // We need to create a method invocation...
                  // Proxy: Proxy object, target: target object, method: method object, args: parameter, targetClass: Proxy class, chain: Proxy logic
      
                  MethodInvocation invocation =
                      new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                  // Proceed to the joinpoint through the interceptor chain.retVal = invocation.proceed(); }... }Copy the code

      Invocation. Proceed () Executes the pointcut for the interceptor chain

      return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
      Copy the code

2. Use of AOP in Spring

  1. Automatic proxy: configuration class

    @ComponentScan("com.anzhi._08Proxy")
    @EnableAspectJAutoProxy
    public class PAppconfig {
    
       // Automatic proxy
       @Bean
       public BeanNameAutoProxyCreator creator(a){
          // Is actually a bean afterprocessor
          BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
          beanNameAutoProxyCreator.setBeanNames("puserService"); // Proxy bean
          beanNameAutoProxyCreator.setInterceptorNames("myAdvisor");  // Proxy logic
          returnbeanNameAutoProxyCreator; }}Copy the code
  2. Implement the PointcutAdvisor interface

    @Component
    public class MyAdvisor implements PointcutAdvisor {
       // Get the pointcut
       @Override
       public Pointcut getPointcut(a) {
          NameMatchMethodPointcut methodPointcut = new NameMatchMethodPointcut();
          methodPointcut.addMethodName("test");
          return methodPointcut;
       }
    
       // Proxy logic
       @Override
       public Advice getAdvice(a) {
          return new MethodBeforeAdvice() {
             @Override
             public void before(Method method, Object[] args, Object target) throws Throwable {
                System.out.println("Method before execution"); }}; }@Override
       public boolean isPerInstance(a) {
          return false; }}Copy the code

    Testing:

    AnnotationConfigApplicationContext context =
          new AnnotationConfigApplicationContext(PAppconfig.class);
    
    PUserService service = context.getBean("PUserService", PUserService.class);
    service.test();
    Copy the code

The comments in the previous code say that BeanNameAutoProxyCreator is actually a post-processor

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
      implements SmartInstantiationAwareBeanPostProcessor.BeanFactoryAware {....}
Copy the code

PostProcessAfterInitialization method is realized

/ / normal AOP @ Override public Object postProcessAfterInitialization (@ Nullable Object bean, String beanName) throws BeansException { if (bean ! = null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); // earlyProxyReferences stores beans that have been AOP in advance, BeanName: before AOP object / / attention earlyProxyReferences did not save after AOP proxy objects in the if (this. EarlyProxyReferences. Remove (cacheKey)! = bean) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }Copy the code
  1. WrapIfNecessary (bean, beanName, cacheKey) generates proxy objects

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
       // The bean that exists in the current targetSourcedBeans, indicating that the proxy object was generated before instantiation
       if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
          return bean;
       }
       // The current bean does not use a proxy
       if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
          return bean;
       }
       // If it is an underlying bean, or the @aspect modified class does not need to be proxied
       // If the current bean type is Pointcut, Advisor,Advice, etc., AOP is not required
       if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
          this.advisedBeans.put(cacheKey, Boolean.FALSE);
          return bean;
       }
    
       // Create proxy if we have advice.
       // Get the advisors matched by the current beanClass, whether dynamic proxy is required
       Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
       // If the matching advisors are not equal to null, then the proxy is performed and the proxy object is returned
       if(specificInterceptors ! = DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);
          // Create proxy objects based on bean objects and advisors
          Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
          // Store the contents of a proxy object
          this.proxyTypes.put(cacheKey, proxy.getClass());
          return proxy;
       }
    
       this.advisedBeans.put(cacheKey, Boolean.FALSE);
       return bean;
    }
    Copy the code
  2. CreateProxy Creates a dynamic proxy object

    protected Object createProxy(Class<? > beanClass,@Nullable String beanName,
                                 @Nullable Object[] specificInterceptors, TargetSource targetSource) {
    
        if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
            AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
        }
        // Create a proxy factory
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);
        // Whether cglib must be used for proxy
        if(! proxyFactory.isProxyTargetClass()) {// If no cglib proxy is specified, then the BeanDefinition should use cglib proxy.
            if (shouldProxyTargetClass(beanClass, beanName)) {
                // Specify proxyTargetClass as true
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                // Whether to use JDK dynamic proxies. If the current beanClass implements an interface, JDK dynamic proxies will be usedevaluateProxyInterfaces(beanClass, proxyFactory); }}// Integrate commonInterceptors and specificInterceptors together
        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors); // Add advisors to proxyFactory
        proxyFactory.setTargetSource(targetSource); // The proxied object
        customizeProxyFactory(proxyFactory);
    
        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }
        return proxyFactory.getProxy(getProxyClassLoader());
    }
    Copy the code
  3. BuildAdvisors (beanName specificInterceptors) integration

    protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
        // Handle prototypes correctly...
        Get Interceptors set manually by setInterceptorNames(). AbstractAutoProxyCreator
        < abstractautoXyCreator > < abstractautoxycreator
        Advisor[] commonInterceptors = resolveInterceptorNames();
    
        List<Object> allInterceptors = new ArrayList<>();
        // Only if specificInterceptors are not null will allInterceptors have a value and will be proxyed
        if(specificInterceptors ! =null) {
            allInterceptors.addAll(Arrays.asList(specificInterceptors));
            if (commonInterceptors.length > 0) {
                if (this.applyCommonInterceptorsFirst) {
                    allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
                }
                else{ allInterceptors.addAll(Arrays.asList(commonInterceptors)); }}}if (logger.isDebugEnabled()) {
            int nrOfCommonInterceptors = commonInterceptors.length;
            intnrOfSpecificInterceptors = (specificInterceptors ! =null ? specificInterceptors.length : 0);
            logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
                         " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
        }
    
        Advisor[] advisors = new Advisor[allInterceptors.size()];
        for (int i = 0; i < allInterceptors.size(); i++) {
            advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
        }
        return advisors;
    }
    Copy the code

    Advice is eventually encapsulated as advisor: addAdvice

    @Override
    public void addAdvice(int pos, Advice advice) throws AopConfigException {
       Assert.notNull(advice, "Advice must not be null");
       if (advice instanceof IntroductionInfo) {
          // We don't need an IntroductionAdvisor for this kind of introduction:
          // It's fully self-describing.
          addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
       }
       else if (advice instanceof DynamicIntroductionAdvice) {
          // We need an IntroductionAdvisor for this kind of introduction.
          throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
       }
       else {
          addAdvisor(pos, newDefaultPointcutAdvisor(advice)); }}Copy the code

At this point the object for dynamic proxy is created. But this automatic configuration is not powerful enough, and you still need to manually specify the objects for the proxy. The following one does not require configuration

// Those beans need to be proxied,
// What is the proxy logic
// Still a BeanPostProcessor
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(a){
   DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
   return creator;
}
Copy the code

AbstractAutoProxyCreator subclasses AbstractAdvisorAutoProxyCreator to judge whether to realize the dynamic proxy

@Override
@Nullable
protectedObject[] getAdvicesAndAdvisorsForBean( Class<? > beanClass, String beanName,@Nullable TargetSource targetSource) {

   // Find qualified advisors for the current bean
   List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
   if (advisors.isEmpty()) {
      return DO_NOT_PROXY;
   }
   return advisors.toArray();
}
Copy the code
  1. FindEligibleAdvisors lookup Advisor

    protected List<Advisor> findEligibleAdvisors(Class
              beanClass, String beanName) {
       // Get all advisors
       List<Advisor> candidateAdvisors = findCandidateAdvisors();
       // Filter
       List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
       
       // Provide additional add advisor to subclasses
       extendAdvisors(eligibleAdvisors);
       if(! eligibleAdvisors.isEmpty()) {// Sort by order
          eligibleAdvisors = sortAdvisors(eligibleAdvisors);
       }
       // Returns the matching Advisor
       return eligibleAdvisors;
    }
    Copy the code

Use annotations directly:

// Can scan all advisors and classes annotated with @aspect
@EnableAspectJAutoProxy
Copy the code

Summary :(according to the notes of zhou yu, lu ban)

1. Concept of AOP:

1. Advice and Advisor

Advice: it is recommended that

In Spring, Advice is broken down into the following parts:

  1. Preadvice: MethodBeforeAdvice

  2. Afteradvice: AfterReturningAdvice

  3. Surround Advice: MethodInterceptor

  4. Exception Advice: ThrowsAdvice

For Advice, it just means “Advice”, it doesn’t say what the “Advice” can be used for, as in, we’ve done a feature and the customer has made a suggestion for that feature, but that suggestion might be used for other functions as well. At this point, there are advisors, which indicate where an Advice can be applied, and “where” is the Pointcut.

2. Pointcut

Pointcuts: indicates that I want those locations plus my proxy logic

Like a method,

Like some methods,

For example, some methods whose names are prefixed with “find”,

Like all the methods under a class, and so on.

In the Pointcut, there is a MethodMatcher, which represents a MethodMatcher

3. Create AOP proxies programmatically using ProxyFactory

There are test examples ahead

1. Working principle of ProxyFactory:

ProxyFactory is a proxy object production factory that needs to be configured before generating the ProxyFactory; You then need to decide whether to use JDK dynamic proxies or Cglib technology before generating proxy objects

1. JdkDynamicAopProxy creates a proxy object

  1. Gets the collection of interfaces that need to be implemented to generate the proxy object

    1. Get through ProxyFactory. AddInterface () add to implement interface, if not through ProxyFactory addInterface add interface (), Then see ProxyFactory. SetTargetClass () set up by the targetClass is an interface, the interface is added to the results in the collection.
    2. Add SpringProxy, Advised, and DecoratingProxy interfaces to the result set
  2. Once the collection to be proxied is determined, a Proxy object is generated using proxy.newProxyInstance ()

2. JdkDynamicAopProxy creates the execution procedure of the proxy object

  1. If by ProxyFactory setExposeProxy () the exposeProxy set to true, then set the proxy objects to a ThreadLocal (currentProxy).

  2. Gets the target set via ProxyFactory. If targetClass is set, target is null

  3. Find the matching Advisor from ProxyFactory based on the currently called method object, and package the Advisor as a MethodInterceptor return, resulting in a MethodInterceptor chain

  4. If chain is null, the current method corresponding to target is executed, or an error is reported if target is null

  5. If the chain is not empty, the MethodInterceptor in the chain is executed in turn

    1. If the current MethodInterceptor is MethodBeforeAdviceInterceptor, then, an executive Advisor advice in before () method, and then execute the next MethodInterceptor
    2. If the current MethodInterceptor is AfterReturningAdviceInterceptor, then, first executed next MethodInterceptor, after get the return value, Then execute the advice afterReturning() method in the Advisor

3. ObjenesisCglibAopProxy Creates a proxy object

  1. Create Enhancer
  2. Set the Enhancer superClass to the class of the object set via proxyfactory.settarget ()
  3. Set Enhancer interfaces by ProxyFactory. AddInterface () to add the interface, and SpringProxy, Advised interface
  4. Set up Callbacks for DynamicAdvisedInterceptor Enhancer
  5. Finally, create a proxy object through Enhancer

4. Execute the proxy object created by ObjenesisCglibAopProxy

In the implementation process mainly depends on DynamicAdvisedInterceptor implementation, execution of logic and JdkDynamicAopProxy is the same.

5. Use AutoProxy

Automatic proxy means that you simply add a Bean to Spring, which is a BeanPostProcessor, and Spring creates a Bean with the judgment of the BeanPostProcessor. To determine whether the Bean currently being created requires AOP.

We can define many advisors in a project in one of two ways:

  1. By implementing the PointcutAdvisor interface
  2. Annotated by @aspect, @pointcut, @before, etc

When a Bean is created, it will match all the defined advisors according to the information of the current Bean, such as the corresponding class and method information in the current Bean. If some of the advisors are matched, these advisors will be found. And add it to ProxyFactory, which uses ProxyFactory to generate proxy objects

@Bean
public BeanNameAutoProxyCreator creator(a){
   // Is actually a bean afterprocessor
   BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
   beanNameAutoProxyCreator.setBeanNames("puserService"); // Proxy bean
   beanNameAutoProxyCreator.setInterceptorNames("myAdvisor");  // Proxy logic
   return beanNameAutoProxyCreator;
}
Copy the code

This bean is an “automatic proxy”. With this bean, you can automatically proxy the beans in setBeanNames. The proxy logic is set to interceptorNames

6. DefaultAdvisorAutoProxyCreator

DefaultAdvisorAutoProxyCreator this even more powerful, as long as add this Bean, it will automatically identify all the PointCut in the Advisor agent

AbstractAutoProxyCreator SmartInstantiationAwareBeanPostProcessor interface is achieved, is a BeanPostProcessor

  1. Before instantiating a Bean, check to see if CustomTargetSource is set in AbstractAutoProxyCreator. If so, check to see if the current Bean needs to create a TargetSource. A TargetSource object is created if needed, then AOP creates a proxy object and returns it
  2. If a Bean has a circular dependency, AOP is pre-aop using the getEarlyBeanReference() method
  3. After a Bean is initialized, the wrapIfNecessary() method is called for AOP
  4. In this class provides an abstract method: getAdvicesAndAdvisorsForBean (), said for a Bean match what Advices and Advisors

AbstractAdvisorAutoProxyCreator inherited AbstractAutoProxyCreator, Implements in AbstractAdvisorAutoProxyCreator getAdvicesAndAdvisorsForBean () method, the realization of logic is:

  1. Call findEligibleAdvisors ()

    1. Call findCandidateAdvisors to get all the beans of type Advisor
    2. Filter by beans that are currently going through their life cycle

7. @EnableAspectJAutoProxy

This annotation is added a BeanDefinition AnnotationAwareAspectJAutoProxyCreator type

AspectJAwareAdvisorAutoProxyCreator inherited AbstractAdvisorAutoProxyCreator, rewrite the shouldSkip (Class
beanClass, String beanName) to indicate whether a bean needs AOP. In shouldSkip() :

  1. Get all advisors
  2. Iterate through all advisors and skip if the current bean is AspectJPointcutAdvisor

AnnotationAwareAspectJAutoProxyCreator inherited AspectJAwareAdvisorAutoProxyCreator, rewrite the findCandidateAdvisors () method, It can either find beans of type Advisor or scan out all classes annotated by @Aspect annotations and generate Advisors

8. Annotation and source code correspondence

  1. @ Before corresponding is AspectJMethodBeforeAdvice, direct implementation MethodBeforeAdvice, On it during the dynamic proxy AspectJMethodBeforeAdvice into MethodBeforeAdviceInterceptor, has turned into MethodBeforeAdviceInterceptor

    1. The advice method is executed first
    2. MethodInvocation proceed() executes the next Interceptor, and if there is no other Interceptor executes the target method
  2. The @After counterpart is AspectJAfterAdvice, which implements MethodInterceptor directly

    1. MethodInvocation proceed() first executes the next Interceptor, and if there isn’t another Interceptor executes the target method
    2. Then execute the advice corresponding method
  3. @around corresponds to AspectJAroundAdvice, which implements MethodInterceptor directly

    1. Execute the advice corresponding method directly
  4. @ AfterThrowing corresponding is AspectJAfterThrowingAdvice, realized the MethodInterceptor directly

    1. MethodInvocation proceed() first executes the next Interceptor, and if there isn’t another Interceptor executes the target method
    2. If the Throwable is thrown, the advice method is executed
  5. @ AfterReturning corresponding is AspectJAfterReturningAdvice, implements the AfterReturningAdvice, On it during the dynamic proxy AspectJAfterReturningAdvice into AfterReturningAdviceInterceptor, has turned into MethodInterceptor

    1. MethodInvocation proceed() first executes the next Interceptor, and if there isn’t another Interceptor executes the target method
    2. Execute the above method to get the return value of the final method
    3. Then execute the Advice corresponding method

Flowchart of AOP principles in Spring