• 从底层分析并详解SpringAOP底层实现


    首先分析AOP的实现

      首先切面(Advisor)由通知(Advice)和切点(Pointcut)组成

      包括前置通知后置通知等等最终都会被转化为实现 MethodInterceptor 接口的环绕通知

      先看一段代码了解一下是aop是怎么运作的

      

    首先定义了两个类实现了MethodInterceptor接口,这里的 MethodInvocation 是对原始方法的包装同时也是AOP通知功能的实现方式。

    首先这里method,target,args都是原始对象的方法参数用于反射调用。构造参数中传入集合的是刚刚来两个实现MethodInterceptor的类。

    当这里的proceed方法被调用时,会有一个初始化为0的参数,作用是记录这里第几个调用的Advisor,当所有的Advisor调完后就会执行真正的原始方法。从而形成了递归调用,效果就是我们看到的环绕通知

    这是主程序加效果

    接下来我们看一下Spring如何实现的

    实现时要使用@EnableAspectJAutoProxy注解,它的作用是通过封装Import注解导入一些其他类,它导入了 AnnotationAwareAspectJAutoProxyCreator 类

    由于此类是被保护的所以我采用继承的方法去调用相关方法,并自定义了一个Advisor,同时还通过注解去引入

     
    

    这是主程序

    @Aspect注解的解析

    首先这是一个Bean后处理器方法

    首先把原始工厂和beanName封装在 MetadataAwareAspectInstanceFactory 类中,此类用于保存@Aspect注解标注的类信息,紧接着调用 this.advisorFactory.getAdvisors 方法

    此方法根据类获得方法信息以及注解信息封装为 InstantiationModelAwarePointcutAdvisorImpl 这种类型的Advisor。

    Advisor由Advice和切点表达式组成

    通过 findEligibleAdvisors 方法获取工厂中所有的Advisor,然后根据bean的类型进行匹配做代理

    不过这里值得注意的是导入了一个org.springframework.aop.interceptor.ExposeInvocationInterceptor 这个类,这个类是为了把信息存放在ThreadLocal中暴露给整个线程

    顺带说一下这里的wrapIfNecessary就是存放在三级缓存的那个bean代理的创建方法

    重点在 wrapIfNecessary 方法,这个方法内部会在 getAdvicesAndAdvisorsForBean 方法中

    调用 findEligibleAdvisors 方法

    然后调用createProxy方法

    重点来了

    此方法内部创建一个ProxyFactory对象,他会把传入的Advisor通过装饰器模式把他们转化为实现了MethodInterceptor接口的环绕通知

    proxyTargetClass 和  exposeProxy 

    是@EnableAspectJAutoProxy两个可选项,第一个为false代表默认使用jdk生成动态代理,true的话用Cglib。而exposeProxy为true则代表把生成的代理对象存放在ThreadlocalMap中,这样就可以解决嵌套调用时事务失效的功能。

    然后调用getProxy方法生成代理对象

    然后我们观察代理对象的代理方法

    这里的advised就是ProxyFactory 紧接着调用 getInterceptorsAndDynamicInterceptionAdvice 方法

    此方法内部获取所有的Advisor然后进行方法匹配,如果匹配就会把Advice包装为环绕通知

    首先获得advice,然后包装

    就是这样进行包装,然后通过MethodInvocation获取这些环绕通知,调用invoke这样就可以实现递归嵌套调用,比如前置通知转化为环绕通知后只需要在proceed之前调用就行,就完成了转化

    最终调用

    就是通过创建 Invocation 然后递归调用

    这是官方的proceed实现和我们最开始写的类似

    由于上面说了会默认加入一个 ExposeInvocationInterceptor 类用于暴露代理接下来就是证明

    这里的invocation就是一个ThreadLocal对象它的作用就是让别的MethodInteceptor也可以使用

    就好比通过转化后的 MethodBeforeAdviceInterceptor 就需要用

  • 相关阅读:
    Java 最常见的 200+ 面试题:面试必备
    Centos安装RabbitMQ超详细(必须收藏)
    Redis单线程源码深入解析
    学习笔记10--ASIL分解与冗余功能安全
    MySQL(十一) 用户管理
    netcore webapi action 同时支持 get 和 post 请求
    基于SSM+VUE的药品销售管理系统的设计与实现
    vue3+scss开启写轮眼
    PS怎么给GIF文字上加图片?
    为什么要改变this指向?
  • 原文地址:https://blog.csdn.net/m0_73700925/article/details/138037227