搞懂aop四 原理

package spring.learn.annotation.aopconfig;

import org.springframework.aop.TargetSource;
import org.springframework.aop.aspectj.AbstractAspectJAdvice;
import org.springframework.aop.aspectj.AspectJAfterAdvice;
import org.springframework.aop.aspectj.AspectJAfterThrowingAdvice;
import org.springframework.aop.aspectj.AspectJAroundAdvice;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator;
import org.springframework.aop.framework.ProxyProcessorSupport;
import org.springframework.aop.framework.ReflectiveMethodInvocation;
import org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor;
import org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor;
import org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator;
import org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator;
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * @Description:
 * 注解AOP使用说明:
 * 1)导包
 *      <dependency>
 *          <groupId>org.springframework</groupId>
 *          <artifactId>spring-aspects</artifactId>
 *          <version>5.1.5.RELEASE</version>
 *       </dependency>
 * 2)定义切面类,切面方法
 *      @Pointcut 切点
 *      @Before("pointcut()")
 *      @After("pointcut()")
 *      @Around("spring.learn.annotation.aopconfig.LogAop.pointcut()") 切点的全名使用,配合ProceedingJoinPoint .proceed(); 使用
 *      @AfterReturning(value = "pointcut()",returning = "res")
 *      @AfterThrowing(value = "pointcut()",throwing = "e")
 * 3)启用AOP功能 @EnableAspectJAutoProxy
 *
 * AOP 原理
 *  1)注入 AnnotationAwareAspectJAutoProxyCreator 一个bean,bean的nameorg.springframework.aop.config.internalAutoProxyCreator 负责处理标有@Aspect注解的bean,继承结构如下
 *  {@link AnnotationAwareAspectJAutoProxyCreator }
 *      — {@link AspectJAwareAdvisorAutoProxyCreator}
 *          — {@link AbstractAdvisorAutoProxyCreator} 主要负责 多个增强满足条件的时候,如何有序执行
 *              — {@link AbstractAutoProxyCreator } 主要负责创建具体的代理对象
 *                  — {@link ProxyProcessorSupport }
 *                  - {@link SmartInstantiationAwareBeanPostProcessor }
 *                     - {@link InstantiationAwareBeanPostProcessor }
 *                        - {@link BeanPostProcessor}
 *                  - {@link BeanFactoryAware }
 * 2)创建AnnotationAwareAspectJAutoProxyCreator时机及流程.这个要从特殊的接口说起【InstantiationAwareBeanPostProcessor,BeanPostProcessor】
 *      1、关键点记录
 *      @see AbstractAdvisorAutoProxyCreator#setBeanFactory
 *      @see AbstractAutoProxyCreator#postProcessAfterInitialization 初始化后置处理器
 *      @see AbstractAutoProxyCreator#postProcessBeforeInstantiation 实例化前处理
 *
 *      2、流程
 *          2.1 registerBeanPostProcessors 注册后置处理器,来拦截所有bean的创建(AnnotationAwareAspectJAutoProxyCreator属于后置处理器)
 *          2.2 注册BeanPostProcessor会根据实现PriorityOrdered、Ordered的接口排序,没有实现的不排序,排序规则按照从小到大,越小的执行
 *          越优先。注册完成后将后置处理器交给bean工厂
 *          2.3 创建bean(该流程适用所有的bean的创建)
 *          @see AbstractBeanFactory#doGetBean 先检查单例缓存是否有手动注册的单例,如果获取不到去继续
 *          @see DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory) 再次尝试获取bean,如果获取不到就创建bean
 *          @see AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, Object[])
 *              2.3.1 在实例化之前执行后置处理器InstantiationAwareBeanPostProcessor,如果有对应后置处理器的实现postProcessBeforeInstantiation返回
 *              一个非空的对象,结束继续代理,然后遍历执行该接口的实现类的后置处理方法postProcessAfterInitialization,如果方法返回返回空结束遍历,
 *              将处理前的对象返回,否则直到遍历完所有。如果该方法返回的对象不为空,创建bean结束。
 *              @see AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition)
 *              2.3.2 前面流程走完如果没有创建的对象,则继续创建。
 *              @see AbstractAutowireCapableBeanFactory#doCreateBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
 *                  2.3.2.1 实例化bean
 *                  @see AbstractAutowireCapableBeanFactory#createBeanInstance(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
 *                  2.3.2.2 实例化后 允许后置处理器MergedBeanDefinitionPostProcessor修改bean的定义信息
 *                  2.3.2.3 初始化bean之属性赋值,先调用实例化的后置处理器postProcessAfterInstantiation,如果返回false则结束赋值;进行属性赋值;
 *                  属性赋值后,有机会执行 InstantiationAwareBeanPostProcessor#postProcessProperties,和postProcessPropertyValues
 *                  @see AbstractAutowireCapableBeanFactory#populateBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, org.springframework.beans.BeanWrapper)
 *                  2.3.2.3 初始化bean之初始化逻辑
 *                  @see AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
 *                      ·invokeAwareMethods执行知道的aware方法(BeanNameAware、BeanFactoryAware、BeanClassLoaderAware)
 *                      @see AbstractAutowireCapableBeanFactory#invokeAwareMethods
 *                      ·执行bean的初始化后置处理器的postProcessBeforeInitialization方法,具体可见lifecyle中的描述
 *                      @see AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
 *                      ·执行初始化方法,使用见lifecycle
 *                      @see AbstractAutowireCapableBeanFactory#invokeInitMethods
 *                      ·执行bean的初始化后置处理器的applyBeanPostProcessorsAfterInitialization方法
 *                      @see AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
 *                      ·todo 后面的逻辑暂时不做跟进
 * 3)创建代理对象,这个时候前面注册的bean,就会在满足条件的bean创建一个代理对象。
 *      1、在对象实例化之前执行实例化的后置处理器,这个时候做一些判断,其中shouldSkip是一个要点,这个方法会查找所有的候选增强并缓存,查找规则
 *       ①按照Advisor这个类型查找,这个是spring支持的增强;②构建AspectJ的增强,这个就是工作中常用的注解增强。
 *      然后遍历这些增强来判断if (advisor instanceof AspectJPointcutAdvisor && ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) ,这个判断是true,则返回true
 *      如果我们有自定义的 {@link TargetSource},在此处创建代理,就回产生一个代理对象,并将bean的名字放在targetSourcedBeans set集合中
 *      如果后面在为bean做增强代理的时候,会检查有没有被增强过,如果增强则不再继续增强了。
 *      @see AbstractAutoProxyCreator#postProcessBeforeInstantiation(java.lang.Class, java.lang.String)
 *          @see AspectJAwareAdvisorAutoProxyCreator#shouldSkip(java.lang.Class, java.lang.String)
 *      2、在对象初始化化之后调用实例化的后置处理器postProcessAfterInitialization,如果需要代理会调用wrapIfNecessary,这个方法再次用到了shouldSkip
 *      @see AbstractAutoProxyCreator#postProcessAfterInitialization(java.lang.Object, java.lang.String)
 *          @see AbstractAutoProxyCreator#wrapIfNecessary(java.lang.Object, java.lang.String, java.lang.Object)
 *          2.1、判断是否有必要包装增强
 *          2.2、 获取这个bean可用的增强方法,先获取候选的,再获取可用的,
 *          @see AbstractAdvisorAutoProxyCreator#findEligibleAdvisors(java.lang.Class, java.lang.String)
 *              2.2.1 findCandidateAdvisors,找到候选的增强,这个方法在shouldSikp中执行过
 *              2.2.2 findAdvisorsThatCanApply 找到候选中可以应用到当前bean的方法。
 *              调用AopUtils中的方法{@link AopUtils#findAdvisorsThatCanApply(java.util.List, java.lang.Class)}这个方法会处理当前bean再在候选增强中能有几个增强可用
 *              2.2.3 extendAdvisors 如果候选方法能应用到正在创建的bean,则再增加一个DefaultPointcutAdvisor,这个增强使用见aop流程分析里
 *              2.2.4 如果可用的增强不为空,则进行排序,按照切面的order排序从小到大排序,再按照切面的增强方法排序{@link AbstractAspectJAdvice}增强都是这个抽象类的实现,这个定义了增强执行
 *              @see org.springframework.aop.aspectj.autoproxy.AspectJPrecedenceComparator#compare(org.springframework.aop.Advisor, org.springframework.aop.Advisor)
 *          2.3、创建代理对象,如果前面能找到可用的增强的话。这里有一些东西需要说明一下,省的混乱。
 *          代理工厂创建了一个DefaultAopProxyFactory对象,这个对象可以根据目标类判断创建何种代理,代理负责创建代理对象
 *          @see AbstractAutoProxyCreator#createProxy(java.lang.Class, java.lang.String, java.lang.Object[], org.springframework.aop.TargetSource)
 *              2.3.1 创建代理工厂,这里使用无参构造器创建了一个默认aop代理工厂DefaultAopProxyFactory,这里预留了扩展{@link AbstractAutoProxyCreator#customizeProxyFactory(org.springframework.aop.framework.ProxyFactory)}
 *              2.3.2 创建代理这个时候默认的aop代理工厂会判断创建jdk还是cglib的对象
 *               @see org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy
 *              2.3.3 创建代理对象
 *              @see org.springframework.aop.framework.CglibAopProxy#getProxy(java.lang.ClassLoader)
 * 4) 代理对象的执行流程
 * @see org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], org.springframework.cglib.proxy.MethodProxy)
 *      1、新建一个方法调用,处理代理对象的方法调用new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
 *      @see ReflectiveMethodInvocation#proceed(),
 *      2、如果匹配的拦截方法的size为0,则执行目标方法,如果不相等,则取出匹配的第一个拦截方法
 *      // currentInterceptorIndex 值默认为-1
 *      if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
 *          return invokeJoinpoint();
 *      }
 *      @see ReflectiveMethodInvocation#proceed()
 *          2.1、取出第一个方法拦截器,执行invoke方法,将当前新建的方法调用设为线程共享变量,如果和面调用链有
 *          需要和这个方法调用对象,可以通过这个类的currentInvocation这个静态无参方法获取
 *          @see ExposeInvocationInterceptor#invoke
 *          2.2、去除第二个方法拦截器,继续执行invoke,这个方法拦截器如果放生异常,则会进入该方法的catch块,执行增强逻辑
 *          @see AspectJAfterThrowingAdvice#invoke
 *          2.3 第三个,如果这个方法执行结束并没有异常,则执行增强逻辑
 *          @see AfterReturningAdviceInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
 *          2.4 第四个,这个方法执行结束前,执行增强逻辑
 *          @see AspectJAfterAdvice#invoke
 *          2.5 第五个,开始执行环绕增强
 *          @see AspectJAroundAdvice#invoke(org.aopalliance.intercept.MethodInvocation)
 *          2.6 before
 *          @see MethodBeforeAdviceInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
 *          注:所有的增强是通过反射执行的
 *          @see AbstractAspectJAdvice#invokeAdviceMethod(org.aspectj.lang.JoinPoint, org.aspectj.weaver.tools.JoinPointMatch, java.lang.Object, java.lang.Throwable)
 *
 * @Author: liangjunhui
 * @Date: 2019/4/2 20:56
 */
@EnableAspectJAutoProxy(proxyTargetClass = true)
@Configuration
public class TestAopConfig {
    @Bean
    public Mathcalcultar caccultar1(){
        return new Mathcalcultar();
    }

    @Bean
    public LogAop logAop(){
        return new LogAop();
    }
}
package spring.learn.annotation.aopconfig;

public class Mathcalcultar {
    public int div(int n,int m){
        return n / m;
    }
}
Mathcalcultar
package spring.learn.annotation.aopconfig;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.Ordered;

import java.util.Arrays;
import java.util.List;

@Aspect
public class LogAop implements Ordered {
    @Pointcut("execution(public int spring.learn.annotation.aopconfig.Mathcalcultar.*(..))")
    public void pointcut(){

    }
    @Before("pointcut()")
    public void methodBefore(JoinPoint joinPoint){
        System.out.println(joinPoint.getSignature().getName()+"方法前执行,方法内的参数"+Arrays.asList(joinPoint.getArgs()));
    }

    @Override
    public int getOrder() {
        return 2147481648;
    }

     @AfterReturning(value = "pointcut()",returning = "res")
    public void methodAfterReturning(JoinPoint joinPoint,Object res){
        System.out.println(joinPoint.getSignature().getName()+"方法返回后执行,方法内的参数"+Arrays.asList(joinPoint.getArgs()));
        System.out.println("返回结果是:"+res);
    }

    @AfterThrowing(value = "pointcut()",throwing = "e")
    public void methodAfterThrowing(JoinPoint joinPoint , Exception e){
        System.out.println(joinPoint.getSignature().getName()+"方法异常后执行,方法内的参数"+Arrays.asList(joinPoint.getArgs()));
        System.out.println("异常信息:");
        e.printStackTrace();
    }

   @Around("spring.learn.annotation.aopconfig.LogAop.pointcut()")
   public Object methodAround(ProceedingJoinPoint joinPoint){
       List<Object> objects = Arrays.asList(joinPoint.getArgs());
       try {
           return joinPoint.proceed();
       } catch (Throwable throwable) {
           throwable.printStackTrace();
       }
       System.out.println(joinPoint.getSignature().getName()+"方法间执行,方法内的参数"+Arrays.asList(joinPoint.getArgs()));
       return null;
   }

    @After("pointcut()")
    public void methodAfter(JoinPoint joinPoint){
        System.out.println(joinPoint.getSignature().getName()+"方法后执行,方法内的参数"+ Arrays.asList(joinPoint.getArgs()));
    }
}
LogAop
原文地址:https://www.cnblogs.com/mao-yan/p/13554768.html