前提回顾

前一篇文章主要介绍了spring核心特性机制的IOC容器机制和核心运作原理,接下来我们去介绍另外一个较为核心的功能,那就是AOP容器机制,主要负责承接前一篇代理模式机制中动态代理:JDKProxy和CglibProxy的功能机制之后,我们开始研究一下如何实现一下相关的AOP容器代理机制的。

AOP入口机制

如何实现将Aspectj的动态weave织入到Spring容器的Bean中?

实现的基本实现原理就是后置处理器:BeanPostProcessor机制,实现动态化植入机制。

如何实现相关的Aspectj的weave织入时机

bean在初始化的时候会进行调用对应的BeanPostProcessor的对应的方法会进行织入。

判断的基本流程

主要取决于wrapIfNecessary方法:

判断当前的Bean是AOP的基础设施类型

如果是基础设施类型,则直接回进行返回该bean对象,不会进行相关的初始化对应的aspectj的动态织入机制。

如果属于定制化的bean对象类型

会进行寻找相关的Bean对应的何时的加强通知类。

如果对应该对象的通知增强数组集合不为空

则会对该bean对象,额外进行增强操作生成相关的代理对象,并返回该执行之后的对象,否则会直接返回该对象即可。

筛选何时的通知器

getAdvicesAndAdvisorsForBean方法是我们筛选Advice增强类的核心方法,主要用于过滤和筛选对应该bean的何时的增强器数组信息。

查找对应Bean的通知增强器

主要用于调用AnnotationAwareAspectJAutoProxyCreatorfindCandidateAdvisors()方法,其内部会进行先关的核心构建相关的Aspectj的类的相关实现操作

构建先关Aspectj类buildAspectJAdvisors方法

  1. 首先先进行获取先关的所有容器的BeanName数据集合
  2. 在根绝上面的BeanName名称集合获取相关的BeanType类型集合
  3. 根据BeanType判断当前的Bean是否属于一个Aspectj的注解.类,如果不是则类不做任何处理。

构建实际的相关的Advisors类机制

advisorsFactory.getAdvisors获取通知器

切点处理

切点类处理操作到此为止,还不完整接下来才是构建动态代理对象的真正执行操作,

  1. 获取上面操作中获取到的Aspectj类中的除了PointCut注解修饰的其他的方法列表。
  2. 根据对应的Aspectj类和相关的Advisors方法列表,创建相关的Advisor实现类,其中内部会进行遍历相关上一步的方法列表,并且调用对应的方法method对应的getAdvisor方法,建立Advisor对象。
  3. 创建相关的AspectJExpressionPointCut对象,并且从方法里的注解表达式进行解析,这最后设置到对应的门面层的Advisor对象实例。
  4. 实际的Advisor对象实现类对象的实际:InstantitationModelAwarePoincutAdvisorImpl实例,并且调用其内部的instantiateAdvice方法构建通知机制。
  5. 其内部仍然会调用getAdvice方法,并且构建相关的注解的类型创建相应的通知。

筛选何时的通知器并且执行应用

findAdvisorsThatCanApply方法

扩展相关的筛选出的通知器列表,extendAdvisors方法,通知器列表首部添加一个DefaultPointcutAdivosr类型的通知器,也就是ExposeInvocationInterceptor.ADVISOR的实现机制。

创建代理对象

  • jdk动态代理
  • cglib动态代理
proxy-target-class

proxy-target-class的属性值,代表是否可以支持代理实现类,默认采用的false代表着,当bean有实现接口的时候,会直接采用jdk的动态代理机制生成代理对象,如果是true,则代表着使用cglib进行生成代理对象。

例如:
<aop:aspectj-autoproxy proxy-target-class = "true" /></aop>
AopProxy接口
  • CglibAopProxy接口实现
  • JdkDynamicAopProxy接口实现

AOP代理对象调用同类的方法问题解决方案

expose-proxy作用

前提是必须要配置相关的expose-proxy属性配置值为true,才会进行暴露对应的代理机制。

为了解决目标方法调用同对象中的其他方法,其他方法的切面逻辑是无法实现,因为会涉及到相关的this操作而不是proxy对象机制。

可以实现使用AopContext.currentProxy()强制转换为当前的代理对象。

拦截器链路执行

intercept方法机制

获取相关的对应方法的拦截器栈链路,如果没有获取到相关的缓存链路,则会直接调用相关的getInterceptorsAndDynamicInterceptorAdvice获取先关的拦截器链。

方法拦截器相关的拦截操作连接点

会进行先关的PointcutAdvisor类型通知器,这里会调用相关的通知器所持有的切点(Pointcut)对类和方法进行匹配,匹配冲过这说明相关的向当前的方法进行织入逻辑控制。此外还会通过geIntercptors()方法对非MethodIntercptor类型的通知进行转换。返回相关的拦截器数组,并且随后存入缓存中。

执行目标方法的方式

如果拦截器为空

则会直接通过代理机制的反射控制进行调用执行即可。

如果不为空

则例如jdkDynamicAutoProxy对象进行调用构建ReflectiveMethodInvocation对象,例如它的process方法启动拦截器栈的invoke方法。

  • invoke:执行拦截器栈
  • invokeJoinpoin():执行目标方法

处理返回值,并且返回该值。

【Spring专场】「AOP容器」不看源码就带你认识核心流程以及运作原理的更多相关文章

  1. 【Spring专场】「IOC容器」不看源码就带你认识核心流程以及运作原理

    这是史上最全面的Spring的核心流程以及运作原理的分析指南 [Spring核心专题]「IOC容器篇」不看繁琐的源码就带你浏览Spring的核心流程以及运作原理 [Spring核心专题]「AOP容器篇 ...

  2. 【Spring专场】「MVC容器」不看源码就带你认识核心流程以及运作原理

    前提回顾 之前已经写了很多问斩针对于SpringMVC的的执行原理和核心流程,在此再进行冗余介绍就没有任何意义了,所以我们主要考虑的就是针对于SpringMVC还没但大框架有介绍的相关内容解析分析和说 ...

  3. 如何让 Spring Security 「少管闲事」

    记两种让 Spring Security「少管闲事」的方法. 遇到问题 一个应用对外提供 Rest 接口,接口的访问认证通过 Spring Security OAuth2 控制,token 形式为 J ...

  4. 专治不会看源码的毛病--spring源码解析AOP篇

    昨天有个大牛说我啰嗦,眼光比较细碎,看不到重点.太他爷爷的有道理了!要说看人品,还是女孩子强一些.原来记得看到一个男孩子的抱怨,说怎么两人刚刚开始在一起,女孩子在心里就已经和他过完了一辈子.哥哥们,不 ...

  5. Spring AOP源码解析——专治你不会看源码的坏毛病!

    昨天有个大牛说我啰嗦,眼光比较细碎,看不到重点.太他爷爷的有道理了!要说看人品,还是女孩子强一些. 原来记得看到一个男孩子的抱怨,说怎么两人刚刚开始在一起,女孩子在心里就已经和他过完了一辈子.哥哥们, ...

  6. Spring中AOP相关的API及源码解析

    Spring中AOP相关的API及源码解析 本系列文章: 读源码,我们可以从第一行读起 你知道Spring是怎么解析配置类的吗? 配置类为什么要添加@Configuration注解? 谈谈Spring ...

  7. Spring Boot启动命令参数详解及源码分析

    使用过Spring Boot,我们都知道通过java -jar可以快速启动Spring Boot项目.同时,也可以通过在执行jar -jar时传递参数来进行配置.本文带大家系统的了解一下Spring ...

  8. Spring Cloud系列(四):Eureka源码解析之客户端

    一.自动装配 1.根据自动装配原理(详见:Spring Boot系列(二):Spring Boot自动装配原理解析),找到spring-cloud-netflix-eureka-client.jar的 ...

  9. Spring PropertyResolver 占位符解析(二)源码分析

    Spring PropertyResolver 占位符解析(二)源码分析 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) ...

随机推荐

  1. typeScript基本概念

    我一直认为学习是知识的累加,而前端技术也是进步的.所以学习的重点就是,'它有什么不同,它好在哪里'.这要求我们必须结合之前的经验和知识去学习一门新技术,而不是无情的复制粘贴机器. 首先,ts的官方定义 ...

  2. linux文件属性和系统信息

    文件属性 1.权限 权限指某一个用户针对某个文件所能做的操作 1.权限的种类 可读(r) 可写(w) 可执行(x) 无权限(-) 2.权限位 linux中的权限位分为三个部分,分别是属主.属组和其他人 ...

  3. CF1560D Make a Power of Two 题解

    Content 给定一个整数 \(n\).每次操作你可以做两件事情中的一件: 删去这个数中的一个数位(如果这个数只剩下一位,则可以把它删空). 在这个数的右边添加一个数位. 你可以以任意顺序执行无限次 ...

  4. LuoguB2001 入门测试题目 题解

    Update \(\texttt{2021.7.3}\) 经测试,本题 \(a,b\) 范围在 long long,对代码进行了修改,并修改一些笔误,更新了数据范围. \(\texttt{2021.7 ...

  5. Birt报表设置自定义的值

    比如数据库查出该字段的值有"no",有"yes",那么想要根据当是no是显示"未完成",当是yes时显示"已完成" 可以 ...

  6. 从go程序中发消息给winform(C#)

    背景: 1.服务端语言为GO,客户端语言为:C#(WinForm): 2.在客户端操执行长耗时任务时,服务器应该将后台日志或定时将心跳信息及时传递给客户端,这样方便用户查看服务器执行情况(重要). 一 ...

  7. Semaphore信号量源码解析

    介绍 Semaphore是什么 Semaphore可以称为信号量,这个原本是操作系统中的概念,是一种线程同步方法,配合PV操作实现线程之间的同步功能.信号量可以表示操作系统中某种资源的个数,因此可以用 ...

  8. Spring学习(一)idea中创建第一个Spring项目

    1.前言 Spring框架是一个开放源代码的J2EE应用程序框架,由Rod Johnson发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container). Sprin ...

  9. SpringBoot项目 maven打包时候提示程序包xxx不存在

    A模块依赖B模块 A打包的时候会报程序包xxx不存在 这时候我们看下B模块的pom.xml文件是否加了 <build> <plugins> <plugin> < ...

  10. jQuery Validate验证(判断)某个字段是否通过验证

    jQuery Validate 默认只能判断整个表单是否验证通过,但是有时候我们需要对某个字段进行判断 ,可以使用以下方法 var bool=$("整个form表单的ID").va ...