Spring AOP 超详细源码解析
知识章节
基础知识
什么是 AOP
- AOP 的全称是 “Aspect Oriented Programming”,即面向切面编程
- 在 AOP 的思想里面,周边功能(比如性能统计,日志,事务管理等)被定义为切面,核心功能和切面功能分别独立进行开发,然后把核心功能和切面功能“编织”在一起,这就叫 AOP
- AOP 能够将那些与业务无关,却为业务模块所共同调用的逻辑封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性
AOP 基础概念
- 连接点(Join point):能够被拦截的地方,Spring AOP 是基于动态代理的,所以是方法拦截的,每个成员方法都可以称之为连接点
- 切点(Poincut):每个方法都可以称之为连接点,我们具体定位到某一个方法就成为切点
- 增强/通知(Advice):表示添加到切点的一段逻辑代码,并定位连接点的方位信息,简单来说就定义了是干什么的,具体是在哪干
- 织入(Weaving):将增强/通知添加到目标类的具体连接点上的过程
- 引入/引介(Introduction):允许我们向现有的类添加新方法或属性,是一种特殊的增强
- 切面(Aspect):切面由切点和增强/通知组成,它既包括了横切逻辑的定义、也包括了连接点的定义。
- AOP 五种通知分类
- 前置通知(Before Advice):在目标方法被调用前调用通知功能
- 后置通知(After Advice):在目标方法被调用之后调用通知功能
- 返回通知(After-returning):在目标方法成功执行之后调用通知功能
- 异常通知(After-throwing):在目标方法抛出异常之后调用通知功能
- 环绕通知(Around):把整个目标方法包裹起来,在被调用前和调用之后分别调用通知功能
AOP 简单示例
创建一个配置类,开启 AspectJ 的自动代理功能
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.aspectj")
public class DemoAspectJConfig {// @EnableAspectJAutoProxy 开启注解 aop 功能// 向 spring 容器中注册 AnnotationAwareAspectJAutoProxyCreator
}
新建接口和接口实现类
// 接口
public interface DemoDao {void query();
}// 实现类
@Component
public class DemoDaoImpl implements DemoDao {@Overridepublic void query() {System.out.println("query ......");}
}
创建一个切面
@Aspect
@Component
public class DemoAspect {// 配置切点@Pointcut("execution(* com.aspectj.dao.*.*(..))")public void point(){}// 切点通知@Before("point()")public void beforeAdd(){System.out.println("before-------------");}
}
创建启动类
public class TestAspect {public static void main(String[] args) {// 刷新容器AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(DemoAspectJConfig.class)// 获取 bean 对象DemoDao dao = configApplicationContext.getBean(DemoDao.class);// 代理对象执行dao.query();}
}
启动 main() 方法,可以看到输出的内容,AOP 配置方法执行
Spring AOP 执行流程
源码解读
代码入口
前置处理
判断是否是切面
构建 bean 对象 advisors 流程
① 遍历所有的类
② 判断是否切面,只有切面才会进入后面逻辑
③ 获取每个 Aspect 的切面列表
④ 保存 Aspect 的切面列表到缓存 advisorsCache<beanName,advisors> 中
获取切面列表
到这一步,前置处理已经完成 !
后置处理
获取切面
创建代理对象
对象增强处理流程
① 获取当前 bean 对象 advisors 列表,判断是否为空
② 不为空就创建代理对象
切面执行
实例化 ReflectiveMethodInvocation 对象,调用 proceed() 方法
第一次递归
数组的第一个对象是 ExposeInvocationInterceptor,执行 invoke(),注意入参是 ReflectiveMethodInvocation
第二次递归
数组的第二个对象是 MethodBeforeAdviceInterceptor,执行 invoke()
第三次递归
如果 advisor 有后置处理,就执行第三次递归
跳出递归
总结
- AOP 实现原理
- 将所有的切面都保存在缓存中
- 取出缓存中的切面列表,和 bean 对象的所有方法匹配,拿到属于 bean 对象的切面列表
- 创建 AOP 代理对象
- 通过 “责任链 + 递归”,去执行切面逻辑
Spring AOP 超详细源码解析相关推荐
- 深入理解MyBatis一级缓存和二级缓存【超详细源码解析】
视频地址:https://www.bilibili.com/video/BV1nP411A7Gu MyBatis的缓存是一个常见的面试题 一级缓存的作用域为何是 sqlSession.二级缓存的作用域 ...
- spring 注解试事物源码解析
spring 注解试事物源码解析 基于xml注解式事务入口 public class TxNamespaceHandler extends NamespaceHandlerSupport {stati ...
- JUC.Condition学习笔记[附详细源码解析]
JUC.Condition学习笔记[附详细源码解析] 目录 Condition的概念 大体实现流程 I.初始化状态 II.await()操作 III.signal()操作 3个主要方法 Conditi ...
- Spring事件机制Event源码解析(未完待续)
Spring事件机制Event源码解析(未完待续) 监听器: ApplicationEvent事件 ApplicationListener监听器(观察者) ApplicationEventMultic ...
- Spring原理学习系列之三:Spring AOP原理(从源码层面分析)-------上部
引言 本文是Spring原理分析的第三篇博文,主要阐述Spring AOP相关概念,同时从源码层面分析AOP实现原理.对于AOP原理的理解有利于加深对Spring框架的深入理解.同时我也希望可以探究S ...
- Spring之循环依赖源码解析
目录 1.什么是循环依赖? 2.为什么会出现循环依赖? 3.面对循环依赖问题,我们该如何思考解决? 4.Spring是怎么解决循环依赖的? 5.总结 1.什么是循环依赖? 有两个类Order.Cust ...
- weiler-atherton多边形裁剪算法_EAST算法超详细源码解析:数据预处理与标签生成...
作者简介 CW,广东深圳人,毕业于中山大学(SYSU)数据科学与计算机学院,毕业后就业于腾讯计算机系统有限公司技术工程与事业群(TEG)从事Devops工作,期间在AI LAB实习过,实操过道路交通元 ...
- EAST算法超详细源码解析:数据预处理与标签生成
作者简介 CW,广东深圳人,毕业于中山大学(SYSU)数据科学与计算机学院,毕业后就业于腾讯计算机系统有限公司技术工程与事业群(TEG)从事Devops工作,期间在AI LAB实习过,实操过道路交通元 ...
- spring系列-注解驱动原理及源码-AOP使用及源码解析
目录 一.用注解方式开启AOP 1.实例 2.AOP简单小结 二.AOP原理 1.@EnableAspectJAutoProxy溯源 2.AnnotationAwareAspectJAutoProxy ...
最新文章
- 安装MySQL时出现黄色感叹号,提示3306已被占用
- 【Linux】Linux中目录结构说明
- implementation of UI5 bindAggregation - busyDialog is handled automatically
- if else if语句的用法python_Python笔记3---if语句、if-elif-else 结构、使用if语句处理列表...
- MySQL的主动优化和被动优化_MySQL“被动”性能优化汇总!
- java的或等于_Java中的“小于或等于”比较运算符是__________: !=|||=|=
- FineUI表格模板列Undefined问题
- apk部分手机安装失败_3关于Apk安装失败问题的解决方法
- Python 字典(dict)操作(update)、翻转字典
- 【学习OpenCV4】如何操作图像中的像素?
- 专利与论文-4:专利申请流程与生命周期及费用
- 阿里云短信验证码购教程(Java演示)
- Unrecognized Windows Sockets error: 10106: Socket creation failed
- python表单数据系统_python 网页提交表单数据库
- vue下载后端返回的压缩包
- iOS开发——设置支持的iOS设备(512m内存以上设备)
- 创业公司 股权分配| 从西少爷股权纷争看初创公司找合伙人与股权分配
- 制动电阻器的工作原理及应用特点
- Android 应用程序开发
- 解决Ubuntu无线网卡突然无法连接
热门文章
- 华为社招16级待遇2020_2020上海建桥学院产品设计(珠宝首饰设计)系16级毕业设计作品展(四)...
- PhotoShop 矢量蒙板
- 拉格朗日中值定理的应用
- WordPress修改WordPress地址和站点地址之后无法打开网站和无法后台登录
- linux 7 内核崩溃重启,centos7无故重启-内核升级
- php的视频怎么保存,premiere怎么保存剪辑好的视频
- 手动管理采购订单周期的挑战以及如何应对
- 2020年清华伯克利(TBSI)预推免面经
- 故事--你不杀伯仁,伯仁确因你而死
- Pandas+Pyecharts | 北京某平台二手房数据分析+可视化