Spring AOP的实现及源码解析
在介绍AOP之前,想必很多人都听说AOP是基于动态代理和反射来实现的,那么在看AOP之前,你需要弄懂什么是动态代理和反射及它们又是如何实现的。
想了解JDK的动态代理及反射的实现和源码分析,请参见下面三篇文章
那么接下里进入AOP的环节。
AOP即面向切面编程,刚学AOP的时候,单是各种AOP的概念都搞的有点懵,什么切面,切点,通知,织入、连接点、目标对象。。。。AOP的原理都没看呢,这些词语的意思就已经让人不想看了。本文将在实现AOP的时候,讲解我理解的这些AOP的术语,对应的AOP的代码和动作。
本文将先从AOP代码实现入手,然后分析AOP的底层代码及其原理。
一、AOP的Demo
如果我们把对象的继承关系看成纵向关系,就像一棵树,多个不同类的多个继承关系就相当于有一排的树。AOP的好处就在于,你想对这些树进行相同的操作时,这个时候,不用纵向的为每个树定义操作方法,你只需要横向的一刀切,给他们提供个共有的操作方法。
Spring的AOP是支持JDK的动态代理和Cglib的动态代理的。JDK的动态代理是针对接口的,而Cglib是针对类的。本文针对JDK的动态代理。
首先定义一个接口:起名字时候特意给这个接口名,带上了Interface,这样后面会更引人注意一些。接口很简单,里面一个抽象方法eat()
package com.weili.cn;
/**
* 动物接口,提供一个eat的抽象方法
* Created by zsqweilai on 17/6/27.
*/
public interface AnimalInterface {
public abstract void eat();
}
实现类:作为一个吃货,实现类里面当然得打印 chi chi chi。撑死我吧!!!
这个实现类里面,只有一个方法,这个方法就是AOP的切点。虽然切点这个概念本身并不一定是Method,但在Spring中,所有的切点都是Method。我们增强的是方法。
切面类,又称增强类。因为我们是要用这个类的方法,来给原先的切点方法增强。切面类中,我们要去执行的方法,称为通知。所谓织入通知,就是将切面类里面的方法,和切点的方法进行联系。
接下来通过xml配置的方式,在xml文件里面配置AOP。
配置<aop:pointcut>的时候,通过expressi表达式,定义了com.weili.cn这个包下的所有类的所有方法 为切入点。也就是说,这个包下的所有方法,在调用执行的时候,会被Spring增强。具体在这里的增强,就是在执行这些切点方法之前和之后,会分别执行animalEmpty 和 animalFull方法。
最后就是调用的方法了。
我得说明一点,在我们进行spring-aop.xml解析的时候,aop还没实现呢。在第二行getBean的时候,才真正进行aop。具体的源码那里 会说明。
紧接着就是Output输出了。所以,我们可以看到,获取的bean,确实是增强后的bean。那么就赶紧看看源码吧。
二、AOP源码分析
源码解析这块,首先就是bean加载。之前也说了,AOP标签也是自定义标签,它的解析也和我们之前自定义标签一样,走自定义标签的解析流程。不同的是,AOP调用的是AOP自己的解析器。由于在 Spring源码解析之二 ------ 自定义标签的解析和注册 中已经很详细的描述了自定义标签的解析流程,所以这里我们就不再去一一看bean标签的解析注册。
所以AOP的源码分析,我们将从调用类里面的第二行,ctx.getBean("animal")开始。在你调试走到这里的时候,在ctx中可以看到解析和注册的bean,我们不妨先来看一下。
如下图,这个是在第一行代码执行完毕后,ctx的各个属性。可以在下图看到,singlentonObjects中,已经存放了代理生成的animal。生层bean的过程在之前的里面已经讲的比较清楚了,这里就不再说明。毕竟AOP嘛,我们需要知道,它是如何在我们需要执行的方法前后将我们需要执行的方法执行完成的。
ctx.getBean("animal")获取完animal bean后,接下来调用eat()方法。这个时候,会进入JdkDynamicAopProxy类的invoke方法。
在这个invoke方法中,先是获取代理类targetClass,然后根据method和targetClass获取此方法对应的拦截器执行链chain。
这个chain的内容如下。通过名字可以看到,一个是afterAdvice,一个是beforeAdvice。获取chain后,构造出一个MethodInvoke方法,然后执行proceed方法。
进入proceed方法。currentInterceptorIndex的初始化值为-1.紧接着就如invoke方法。这里的this是我们的eat方法。
在invoke方法里,这里的mi是我们的interface里面的eat方法。然后执行mi的proceed()方法。
这个时候,会继续回到开始时候的proceed方法。这个时候获取到的是
interceptorOrInterceptionAdvice,也就是前面拦截器的list里面的第二个,after的那个方法。然后继续递归调用,会到链表的最后一个before方法。
最终会调用before里面的方法,
然后回去执行invokeJoinpoint方法,
Spring AOP的实现及源码解析的更多相关文章
- Spring核心框架 - AOP的原理及源码解析
一.AOP的体系结构 如下图所示:(引自AOP联盟) 层次3语言和开发环境:基础是指待增加对象或者目标对象:切面通常包括对于基础的增加应用:配置是指AOP体系中提供的配置环境或者编织配置,通过该配置A ...
- Spring MVC工作原理及源码解析(三) HandlerMapping和HandlerAdapter实现原理及源码解析
1.HandlerMapping实现原理及源码解析 在前面讲解Spring MVC工作流程的时候我们说过,前端控制器收到请求后会调⽤处理器映射器(HandlerMapping),处理器映射器根据请求U ...
- Spring IOC和Spring AOP的实现原理(源码主线流程)
写在前面 正本文参考了<spring技术内幕>和spring 4.0.5源码.本文只描述原理流程的主线部分,其他比如验证,缓存什么可以具体参考源码理解. Spring IOC 一.容器初始 ...
- SpringBoot 源码解析 (八)----- Spring Boot 精髓:事务源码解析
本篇来讲一下SpringBoot是怎么自动开启事务的,我们先来回顾一下以前SSM中是如何使用事务的 SSM使用事务 导入JDBC依赖包 众所周知,凡是需要跟数据库打交道的,基本上都要添加jdbc的依赖 ...
- 【SSH进阶之路】Spring的IOC逐层深入——源码解析之IoC的根本BeanFactory(五)
我们前面的三篇博文,简单易懂的介绍了为什么要使用IOC[实例讲解](二).和Spring的IOC原理[通俗解释](三)以及依赖注入的两种常用实现类型(四),这些都是刚开始学习Spring IoC容器时 ...
- Spring MVC工作原理及源码解析(二)DispatcherServlet实现原理及源码解析
1.DispatcherServlet 处理流程 从上一篇文章中Spring MVC原理图中我们可以看出:DispatcherServlet 在 Spring MVC框架 中处于核心位置,它负责协调和 ...
- 【spring源码学习】spring的事务管理的源码解析
[一]spring事务管理(1)spring的事务管理,是基于aop动态代理实现的.对目标对象生成代理对象,加入事务管理的核心拦截器==>org.springframework.transact ...
- Spring MVC工作原理及源码解析(四) ViewResolver实现原理及源码解析
0.ViewResolver原理介绍 根据视图的名称将其解析为 View 类型的视图,如通过 ModelAndView 中的视图名称将其解析成 View,View 是用来渲染页面的,也就是将 Mode ...
- Spring事件监听机制源码解析
Spring事件监听器使用 1.Spring事件监听体系包括三个组件:事件.事件监听器,事件广播器. 事件:定义事件类型和事件源,需要继承ApplicationEvent. package com.y ...
随机推荐
- Idea中运行项目时出现:未结束的字符串解决方案
一般出现这种情况是编码不一致导致 解决办法: settings>file Encodings 编码设置成一致
- Python字符串格式化 (%操作符)
在许多编程语言中都包含有格式化字符串的功能,比如C和Fortran语言中的格式化输入输出.Python中内置有对字符串进行格式化的操作%. 模板 格式化字符串时,Python使用一个字符串作为模板.模 ...
- leetcode146
public class LRUCache { ; ; long sernumbers; long SerNumbers { get { if (sernumbers <= long.MaxVa ...
- 4-29 c语言之栈,队列,双向链表
今天学习了数据结构中栈,队列的知识 相对于单链表来说,栈和队列就是添加的方式不同,队列就相当于排队,先排队的先出来(FIFO),而栈就相当于弹夹,先压进去的子弹后出来(FILO). 首先看一下栈(St ...
- 多个css样式合并到一个“目录”css文件中
执行访问jsp后发现没有效果 同样的代码,在html中效果对比如下: 具体原因:不清楚,暂时记着~~~在jsp中不支持@import这种css样式的引用
- 解决:win10在空白处右键资源管理器重启的故障
一,查看windows日志 win+R,输入eventvwr,打开事件查看器,展开左边Windows日志,双击圆形红底白色感叹号图标所在的行. 查找错误模块名称. 对比图标和名称,这是"飞鸽传书"的安 ...
- ArcGIS自定义工具箱-清空工作空间
ArcGIS自定义工具箱-清空工作空间 联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com 目的:删除工作空间里的要素类,栅格和独立表 使用方法: 例如"C:\ ...
- echarts Cannot read property 'getAttribute' of null 问题的解决方法
今天在使用echarts练习官方给的实例的时候,代码没有问题 却总是报错“Cannot read property 'getAttribute' of null” 找了好久的文档没有看明白 ... 最 ...
- java学习笔记(五):公共类
什么是公共类,公共类就是和源文件名同名的类,举例来说:类的名称是 public class aaa{},那么源文件就应该是 aaa.java. 每个源文件中只能有一个公共类. 每个源文件可以有很多非公 ...
- android studio 创建图标
参考 https://www.cnblogs.com/c546170667/p/5975550.html File-New-Image Asset