spring的AOP全流程调用+执行顺序
2020-06-19 14:03:46 50 举报
spring aop的全流程梳理
作者其他创作
大纲/内容
3.创建专门的MetadataAwareAspectInstanceFactory工厂并委托给他去创建切面对象(一个类一个)advisorFactory.getAdvisors(factory);
mi.proceed();传递火炬给Around
2.判断这个类上是不是有@Aspect注解advisorFactory.isAspect(beanType)
进行一个排序sortAdvisors(eligibleAdvisors)
AtAfterReturning
AtAfterThrowing
9
AspectJAfterThrowingAdvice
1.AspectJAfterThrowingAdvice.invoke(mi)
AspectJAroundAdvice
@AfterThrowing
5
proxyFactory.getProxy(getProxyClassLoader());
这是代码的真正调用顺序
任何出错都有可能丢过来
new AfterReturningAdviceInterceptor(advice);
在ReflectiveAspectJAdvisorFactory类中执行真正的委托操作getAdvisors(aspectInstanceFactory)
1.获取spring容器中的bean的 beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(....)
成功11
1.先从工厂里面获得有@Aspect注解的类Class和类名称2.getAdvisorMethods(aspectClass)获取不包含@Pointcut注解的方法3.遍历执行包含Pointcut注解的方法来获取Advisor对象
@After
BeanPostProcess的应用之一。在spring的初始化流程中。在很多地方提供了类似的埋点。目的就是为了实现动态的扩展
成功6
instantiateAdvice(this.declaredPointcut);上面的都是在封装,这个是创建advice对象
执行后置语义块方法
invocation.proceed();火炬创建完毕。点火
this.advisorAdapterRegistry.wrap(allInterceptors.get(i));对自定义的advice要进行包装,把advice包装成advisor对象,切面对象
主要我们来看创建切面这个方法this.aspectJAdvisorsBuilder.buildAspectJAdvisors()
MethodBeforeAdvice
调用链完毕
AOP
10
创建代理对象1.创建代理工厂2.包装成advisor切面3.获取代理实例
4
1.从代理工厂中去除TargetSource对象。再从中拿到target对象(即被代理对象)2.获取对象的Advice处理链3.判断处理链是否为空,为空直接调用不为空就封装成ReflectiveMethodInvocation对象4.之后开始传递火炬invocation.proceed();
1.找到合格切面2.进行类和切面的匹配3.对匹配的切面进行一个排序
1.找封装对象
其他的进入for循环AspectJMethodBeforeAdvice AspectJAfterReturningAdvice主要是这两个,先判断是不是支持这两个,然后包装成统一对象。目的是为了后面进行扩展
创建这个对象做了如下1.把注解信息封装2.从枚举中获取注解的Advice类型(用了后面创建Advice)3.解析注解上的切面表达式(从pointcut或value属性上获取)4.读注解上的参数
6
如果是MethodInterceptor就转换类型加入集合否则遍历支持的适配器有没有匹配的有就获取一个包装对象adapter.getInterceptor(advisor)
自己方法内传火炬pjp.proceed()给before
@Before
3
@Around
成功8
选择合适的实现类实现
失败6
这个类定义了一个currentInterceptorIndex调用的时候开始判断是不是已经全部执行。没有再往下传递,完成了就直接执行原方法
失败11
AspectJAroundAdvice.invoke(mi)
假设我们所有的增强都有。在本类内会进行下这样的一个调用链。调用链和打印结果是反的(这里调用类似压栈操作,新进后出)
多个Aspect的执行顺序(假设已经指定顺序)
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);给当前调用次数+1并获取advice
invoke()
火炬传递回来如果还有Aspect继续传递。这里假设没有了调用本例方法AseinvokeJoinpoint();
@AfterReturning
引介切面并且匹配
new AspectJAnnotation<>(result);
在这之前需要完成对AOP支持类的注册和实例化。对于xml和注解方式原理上都是先转换成了beanDefinition后在refresh的registerBeanPostProcessors(beanFactory);完成了相应的支持类的初始化。具体的这里不在赘述
AbstractAutowireCapableBeanFactoryinitializeBean()大多数AOP代理的入口
DefaultAdvisorChainFactory这个类进行处理操作advisor instanceof PointcutAdvisor省略匹配过程看包装部分registry.getInterceptors(advisor);
1.获取PointCut对象封装成AspectJExpressionPointcut2.没有切点的话就返回。否则就创建Advisor切面对象。(传入pointCut,advice)
是Advisor的转换类型
AspectJMethodBeforeAdvice
递归查找到表达式。然后封装成AspectJAnnotation对象(1.解析注解上面的表达式2.获取注解上的参数)
AspectJAfterAdvice.invoke(mi)
现在上面的部分就已经完成了所谓的代理对象的创建过程了,接下来就是代理对象的调用流程。是一个链式调用方式。首先动态代理的模式决定了他会调用InvocationHandler的Invoke
MethodBeforeAdviceInterceptor
这里先调用了个父类的实现。看看有没有注解的配置切面
BeanFactoryAspectJAdvisorsBuilder创建工作交给这个类去做(委托模式也无可厚非吧)1.获取spring容器中的所有bean的名称之后开始遍历2.先拿到类以后判断类上是不是有@Aspect注解3.通过委托专门的MetadataAwareAspectInstanceFactory创建切面对象
因为我们注册进来的是AnnotationAwareAspectJAutoProxyCreator所有这里会执行子类的findCandidateAdvisors();
AspectJAfterAdvice
1
AspectJAfterReturningAdvice
((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);调用MethodInterceptor中的invoke方法进行一个火炬的传递
AfterReturningAdvice
2.根据aspectJAnnotation.getAnnotationType()类型创建不同的Advice
new MethodBeforeAdviceInterceptor(advice);
1.又执行了一次封装AspectJAnnotation对象的操作2.之后根据该对象的注解类型进行了不同的Advice创建
2
前面都是压栈这里真正触发
这里还不懂引介有啥用。所有先不展开
创建完了一路返回
before方法体
MethodBeforeAdviceInterceptor.invoke(mi)
findAspectJAnnotationOnMethod(candidateAdviceMethod);
ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);
非引介切面匹配
实现了MethodInterceptor创建普通包装对象DefaultPointcutAdvisor
先去获取Class对象获取构造器创建Proxy实例对象
mi.proceed();火炬传递走
around方法体
MethodInterceptor
AfterReturningAdviceInterceptor
this.advised.exposeProxy这个属性是注解@EnableAspectJAutoProxy里可以设置的如果是true把代理对象放一个threaLocal中(没用)
advisor instanceof IntroductionAdvisor这个是引介的判断。历经这两步的判断之后会完成调用链集合的添加
mi.proceed();传递火炬给After
AfterReturningAdviceInterceptor.invoke(mi)
这里有利用到了缓存。对于这个方法的调用链进行了一个缓存methodCache
第一个
失败8
1.从代理工厂中获得该被代理类的所有切面advisor2.匹配是否是要拦截的对象,是否是拦截的方法3.都匹配的情况下进行advice的包装
代理实例方法
AtAround
第二个
AtAfter
7
目标方法Method
JdkDynamicAopProxy
mi.proceed();传递火炬给AfterReturning
afterReturnning方法体
一个Aspect的执行顺序
判断属性上是否有引介注解aspectClass.getDeclaredFields()如果有获取切面
AtBefore
目标方法
CglibAopProxy
这个是打印顺序。真正在方法中压栈和出栈的顺序正好是反的
判断是不是有适配器支持。adapter.supportsAdvice(advice)之后包装成DefaultPointcutAdvisor
after方法体
这里拿到了切面对象后开始创建代理对象。并加入两个缓存(advisedBeans是否要被代理proxyTypes代理类信息)
0 条评论
下一页