SSM框架学习-AOP学习笔记
一、AOP入门简介
AOP(Aspect Oriented Programming)面向切面编程,是一种编程范式,可以知道开发者如何组织程序结构
作用:在不惊动原始设计的基础上为其进行功能增强。(无侵入式编程)
AOP的核心概念:
- 连接点(JoinPoint):程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等。
- 在SpringAOP中可以理解为方法的执行。
- 切入点(PointCut):匹配连接点的式子
- 在SpringAOP中,一个切入点只可以描述 一个具体的方法,也可以匹配多个方法。
- 一个具体方法:com.huawei.dao包下的BookDao接口中的无形参无返回值的save方法。
- 匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法。
- 在SpringAOP中,一个切入点只可以描述 一个具体的方法,也可以匹配多个方法。
- 通知(Advice):在切入点处执行的操作,也就是共性功能。
- 在SpringAOP中,功能最终会以 方法的形式呈现出来。
- 通知类:定义通知的类。
- 切面(Aspect):描述通知与切入点的对应关系。
连接点代表所有的方法,切入点代表要追加功能的方法,在范围上连接点是包含切入点的。
二、AOP工作流程
1、Spring容器启动
2、读取所有切面配置中的切入点
3、初始化bean,判断bean对应的类中的方法是否匹配到任意切入点
- 匹配失败、创建对象
- 匹配成功,创建原始对象(目标对象)的代理对象
4、获取bea执行方法
- 获取bean,调用方法并执行,完成操作
- 获取到的bean是代理对象的时候,根据代理对象的运行模式运行原始方法与增强的内容来完成操作
AOP的核心概念
- 目标对象(Target):原始功能去掉共性功能对应的类产生的对象,这种对象是无法直接完成最终工作的;
- 代理(Proxy):目标对象无法直接完成工作,需要对其进行功能回填,通过原始对象的代理对象实现。
三、AOP切入点表达式
切入点:要增强的方法
切入点表达式:要进行增强的方法的描述方式
描述方式一:执行com.huawei.dao包下的BookDao接口中的无参数update方法
execution(void com.huawei.dao.BookDao.update())
描述方式二:执行com.huawei.dao.impl包下的BookDaoImpl类中的无参数update方法
execution(void com.huawei.dao.impl.BookDaoImpl.update())
切入点表达式标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数)异常名)
可以使用通配符描述切入点,快速描述
*
:单个独立的任意符号,可以独立出现,也可以作为前缀或者后缀的匹配符出现
execution(public * com.huawei.*.UserService.find*(*))
..
:多个连续的任意符号,可以独立出现,常用于简化包名和参数的书写
execution(public User com..UserService.findById(..))
+
:专用于匹配子类的类型
execution(* *..*Service+.*(..))
书写技巧
- 所有代码按照规范标准开发,否则以下的这些技巧会全部失效
- 描述切入点通常描述接口,而不去描述实现类
- 访问修饰符对接口开发均采用public描述(可以省略访问控制修饰符描述)
- 返回值类型对于增删改类使用精准类型加速匹配,对于查询类使用*通配快速描述
- 包名书写尽量不要使用..来匹配,效率过低,通常用*来做单个包的描述匹配,或者精准匹配
- 接口名/类名书写名称与模块相关的采用
*
匹配,例如UserService书写成*
Service,绑定业务接口名 - 方法名书写应该以动词进行精确匹配,名词采用
*
匹配,例如getById书写成getBy*
,selectAll写成selectAll - 参数规则较为复杂,根据业务方法灵活调整
- 通常不使用异常作为匹配规则
四、AOP通知类型
AOP通知描述了抽取的共性功能,根据共性功能抽取的位置不同,最终运行代码的时候需要将其加入到合理的位置。
AOP通知可以分为5种类型:
- 前置通知
- 后置通知
- 环绕通知(重点)
- 返回后通知(了解)
- 抛出异常后通知(了解)
4.1 前置通知
@Before("pt()")
public void before() {
System.out.println("before advice...");
}
4.2 后置通知
@After("pt()")
public void after() {
System.out.println("after advice...");
}
4.3 环绕通知(重点)
@Around("pt()")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around before advice...");
// 表示对原始程序的调用
pjp.proceed();
System.out.println("around after advice...");
}
如果我们采取环绕通知的原函数是有返回值的,那么我们也需要采取对应的写法完善这部分内容:
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around before advice...");
// 表示对原始程序的调用
Object ret = pjp.proceed();
System.out.println("around after advice...");
return ret;
}
@Around注意事项:
1、环绕通知必须依赖形参ProceedingJoinPoint才能实现对原始方法的调用,进而实现原始方法调用前后同时添加通知。
2、通知中如果未使用ProceedingJoinPoing对原始方法进行调用的话就会直接跳过原始方法的执行。
3、对原始方法的调用可以不接收返回值,通知方法设置成void即可,如果需要接收返回值的话,必须设置成Object类型。
4、原始方法的返回值如果是void类型,通知方法的返回值类型可以设置成void,也可以设置成Object。
5、由于无法预知原始方法运行之后是否会抛出异常,因此环绕通知方法必须抛出Throwable对象。
4.4 返回后通知
与正常的后置通知的区别是,返回后通知只有在源程序没有抛出异常,正常结束的情况下才会使用。(了解即可,实际并不常用)
4.5 抛出异常后通知
只有在源程序抛出异常的情况下才会被调用,如果源程序正常结束而没有抛出任何异常的话,则不会被调用。
五、AOP通知获取数据
- 获取切入点方法的参数
- JoinPoint:适用于前置、后置、返回后、抛出异常后通知
- ProceedJointPoint:适用于环绕通知
- 获取切入点方法的返回值
- 返回后通知
- 环绕通知
- 获取切入点方法的运行异常信息
- 抛出异常后通知
- 环绕通知
5.1 对于参数的获取
前置后置方法获取函数参数的demo:
@Before("pt()")
public void before(JoinPoint pj) {
Object[] args = pj.getArgs();
system.out.println(Arrays.toString(args));
System.out.println("before dao ...");
}
环绕通知方法可以拿到参数之后进行一系列处理再传入,具体实现如下:
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
System.out.println(Arrays.toString(args));
// 可以在此处对数据进行清洗或者进一步操作
args[0] == 666;
Object ret = pjp.proceed(args); // 此时就是使用我们新传入的参数进行相关的业务操作了
return ret;
}
5.2 对于返回值的获取
采用环绕通知获取返回值的方法上面已经展示了,因此此处不再赘述。
返回后通知demo:
@AfterReturning(value="pt()", returning="ret") // 此处returning属性就是代表接收返回值的
public void afterReturning(Object ret) {
System.out.println("afterReturning result is : " + ret);
}
需要注意的是,如果afterReturning方法中需要连接点的话,参数位置必须是第一个,也可以直接省略不写,
public void afterReturning(JoinPoint jp, Object ret)
5.3 对于异常的获取
环绕通知中只需要使用try-catch
块包围即可,之后我们可以在catch中对捕获到的异常做出对应的操作。
抛出异常后通知demo:
@AfterThrowing(value="pt()", throwing="t")
public void afterThrowing(Throwable t) {
System.out.println("afterThrowing dao ...");
}
六、案例及总结
6.1 案例
需求:对百度网盘分享链接输入密码时尾部多输入的空格进行兼容性处理
分析:
- 在业务方法执行之前对所有的输入参数进行格式处理
- 适用处理后的参数再去调用原始方法 —— 环绕通知中存在对原始方法的调用
核心实现代码:
@Around("servicePt()")
public Object trimStr(ProceedingJoinPoint pjp) throw Throwable {
Object[] args = pjp.getArgs();
// 循环判断是否需要去除空格
for (int i = 0; i < args.length; i++) {
// 如果判定当前参数是字符串的话,则执行去空格操作
if (args[i].getClass.equals(String.getClass())) {
args[i] = args[i].toSrting().trim();
}
}
Object ret = pjp.proceed(args);
return ret;
}
6.2 AOP学习总结
在AOP的实际实现中,我们比较常用的是环绕通知:
- 环绕通知依赖形参ProceedingJoinPoint才能够实现对原始方法的调用
- 环绕通知可以隔离原始方法的调用执行
- 环绕通知的返回值设置为Object类型
- 环绕通知可以对原始方法调用过程中出现的异常进行处理。
SSM框架学习-AOP学习笔记的更多相关文章
- SSM框架—Spring AOP之基于注解的声明式AspectJ(Demo)
项目结构 XML <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http ...
- SSM框架之AOP、动态代理、事务处理相关随笔
AOP: 原理:底层利用动态代理(两种动态代理技术都使用了) 两种实现方案: 第一种:JDK动态代理技术 实现的InvocationHandler接口,要想实现某个类的动态代理对象,必须有接口有实现类 ...
- Java基础及JavaWEB以及SSM框架学习笔记Xmind版
Java基础及JavaWEB以及SSM框架学习笔记Xmind版 转行做程序员也1年多了,最近开始整理以前学习过程中记录的笔记,以及一些容易犯错的内容.现在分享给网友们.笔记共三部分. JavaSE 目 ...
- SSM框架学习之高并发秒杀业务--笔记2-- DAO层
上节中利用Maven创建了项目,并导入了所有的依赖,这节来进行DAO层的设计与开发 第一步,创建数据库和表. 首先分析业务,这个SSM匡济整合案例是做一个商品的秒杀系统,要存储的有:1.待秒杀的商品的 ...
- IDEA 整合 SSM 框架学习
认识 Spring 框架 更多详情请点击这里:这里 Spring 框架是 Java 应用最广的框架,它的成功来源于理念,而不是技术本身,它的理念包括 IoC (Inversion of Control ...
- Spring MVC 学习总结(十一)——IDEA+Maven+多模块实现SSM框架集成
一.SSM概要 与SSH(Struts/Spring/Hibernate/)一样,Spring+SpringMVC+MyBatis也有一个简称SSM,Spring实现业务对象管理,Spring MVC ...
- Spring入门IOC和AOP学习笔记
Spring入门IOC和AOP学习笔记 概述 Spring框架的核心有两个: Spring容器作为超级大工厂,负责管理.创建所有的Java对象,这些Java对象被称为Bean. Spring容器管理容 ...
- AOP学习笔记一
软件开发的目的是为了解决各种需求,包括业务需求和系统需求.目前,业界通过使用面向对象的编程思想,已经可以对业务需求等普通关注点进行很好的抽象与封装,并且使之模块化.但是对于系统需求一类的关注点来说,情 ...
- Aop学习笔记
在学习编程这段时间我想大家都是习惯了面向过程或者面向对象的思想来编程,较少或者没有接触过面向方面编程的思想. 那么什么是面向方面(Aspect)——其实就是与核心业务处理逻辑无关的切面,例如记录日志. ...
- SSM框架学习思维导图
SSM框架学习思维导图 2017年08月11日 20:17:28 阅读数:1141 放上前段时间学习SSM框架以及Spring.SpringMVC.MyBatis的学习结果,输出思维导图一共四幅图.这 ...
随机推荐
- Keras网络可视化方法
Keras网络可视化方法 Keras模型可视化 Keras可视化依赖的两个包 参考链接 Keras模型可视化 代码: from keras.utils import plot_model plot_m ...
- 《HTTP权威指南》– 2.HTTP报文与URL资源
URL与资源: 大多数URL方案的URL语法都建立在这个由9部分构成的通用格式上. 方案: 访问服务器以获取资源要使用哪种协议 用户: 某些方案访问资源时需要的用户名 密码: 用户名后面可能包含的密码 ...
- centos7安装MySql8.0.29教程
个人名片: 对人间的热爱与歌颂,可抵岁月冗长 Github:念舒_C.ying CSDN主页️:念舒_C.ying 个人博客 :念舒_C.ying @ 目录 1 安装之前检测系统是否有自带的MySQ ...
- web项目部署上线(无虚拟主机,待学习)
购买阿里云服务器 阿里云服务器ECS 系统镜像使用Ubuntu 20.04 LTS 使用ssh连接服务器,终端或者CMD中执行:$ssh root@x.x.x(阿里云服务器账号名@公网地址) 输入账号 ...
- Git学习脑图
背景: 最近在学习Git工作流,学习的是廖雪峰大神的教程,里面也很详尽了,于是自己就用脑图简单归纳自己选择学习的部分,方便日后查阅. 脑图:
- 基于docker容器的MySQL主从设置及efcore读写分离
1.基于docker部署MySQL,设置主从 本操作基于已经拉取的镜像(docker pull mysql) 创建一主一从两个数据库容器 docker run -d -p 3307:3306 -e M ...
- 探讨下如何更好的使用缓存 —— Redis缓存的特殊用法以及与本地缓存一起构建多级缓存的实现
大家好,又见面了. 本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容,将会通过系列专题,讲清楚缓存的方方面面.如果感兴趣,欢迎关注以获取后续更新. 通过前面的文章,我们一起剖析了Guav ...
- 从0开始学Java 第一期 开发前的准备
Java 学习(一) - 开发前的准备 前言 由于一些项目上的需要,我得学习一下 Java 这门语言(主要是想写Android),本人并非0基础,至少在上个学期学习了一门必修的程序设计(C语言),所以 ...
- OpenMP 环境变量使用总结
OpenMP 环境变量使用总结 OMP_CANCELLATION,在 OpenMP 规范 4.5 当中规定了取消机制,我们可以使用这个环境变量去设置是否启动取消机制,如果这个值等于 TRUE 那么就是 ...
- VUEX 使用学习五 : getter
转载请注明出处: Getter对Store中的数据进行加工处理形成新的数据.他不会修改state中的原始数据,起到的是包装数据的作用: 有时我们需要从 store 中的 state 中派生出一些状态, ...