搞懂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; } }
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())); } }