你不是说你会Aop吗?
一大早,小王就急匆匆的跑过来找我,说:周哥,那个记录日志的功能我想请教一下。
因为公司某个项目要跟别的平台做对接,我们这边需要给他们提供一套接口。昨天,我就将记录接口日志的工作安排给了小王。
下面是我跟小王的主要对话。
我:说说怎么了?
小王:我将记录接口日志的功能放到了每个controller中,现在感觉有点繁琐,我这样做是不是不太合适?
我:为什么要去每个接口里记录日志?
小王:最开始我是用的拦截器,但是这样一个请求就记录了两条记录。
我:为什么是两条?
小王:在preHandle中记录一条请求数据,在postHandle中记录一条响应数据。
我:。。。你不是说你会Aop吗?
小王:Aop也是一样,在前置通知记录一条请求数据,后置通知记录一条响应数据。
小王:这个数据和以前记录操作日志的不太一样,以前只需要在前置通知记录一条操作日志就可以了,但是现在有响应,所以只能在controller中记录日志了。
我:那你知不知道有个环绕通知?你说一下Aop就几种通知类型。
小王:总共有五种,分别是:
- 前置通知:在我们执行目标方法之前运行(@Before)
- 后置通知:在我们目标方法运行结束之后,不管有没有异常(@After)
- 返回通知:在我们的目标方法正常返回值后运行(@AfterReturning)
- 异常通知:在我们的目标方法出现异常后运行(@AfterThrowing)
- 环绕通知:目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,joinPoint.procced()就是执行目标方法的代码 。环绕通知可以控制返回对象(@Around)
接下来,我们一起来演示一下如何使用环绕通知来解决小王的问题。
第一步:提供接口用来接收参数和响应接口
@RestController
public class TestController {
@GetMapping("/getName")
public String getName(HttpServletRequest request) throw Exception {
String result = "Java旅途";
String age = request.getParameter("age");
if("18".equals(age)){
result = "无法识别";
}
return result;
}
}
第二步:定义切点
execution()是比较常用的定义切点的表达式,execution()语法如下:
execution(修饰符 返回值 包.类.方法名(参数) throws异常)
其中:
修饰符和throws异常可以省略不写
根据这些解释,我们可以将第一步中的接口用execution()表达式来描述一下:
execution(String binzh.website.controller.TestController.GetName(HttpServletRequest))
*:匹配所有项..:匹配任意个方法参数..出现在类名中时,后面必须跟*,表示包、子孙包下的所有类;
现在我们优化一下上面的表达式,定义切面为controller包及controller下面所有包的所有方法
execution(* binzh.website.controller..*.*(..))
第三步:环绕通知记录日志
@Around("execution(* binzh.website.controller..*.*(..))")
public Object around(ProceedingJoinPoint joinPoint) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String age = request.getParameter("age");
Object proceed = "";
try {
proceed = joinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("age==="+age);
System.out.println("proceed ===="+proceed);
return proceed;
}
运行结果如下:
age===19
proceed ====Java旅途
我们之所以可以用环绕通知来处理小王的问题。其中一个重要的原因就是,我们提供的所有接口都是经过统一加密的,最后请求的参数都是一个固定的名字。还需要注意的一点就是,环绕通知的返回值类型必须大于等于方法的返回值,即:加入你方法返回String类型,环绕通知不能写成void类型。
小王看到这里后,恍然大悟,准备赶紧回去试一下。我急忙拉住他。
我:如果接口出现异常了怎么办?
小王:那我在异常通知里处理就可以了。
我:你再想一下?
小王:好像不行,异常通知里获取不到请求参数。
我:在环绕通知中捕获处理可以吗?
这时候,看见小王眼睛发光,惊讶的说了一句:环绕通知太牛批了,竟然可以完成前置通知、后置通知和异常通知的工作!
这篇文章戏有点多,别见怪。实战是提升技术最有效的途径!
你不是说你会Aop吗?的更多相关文章
- 基于spring注解AOP的异常处理
一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...fin ...
- Spring基于AOP的事务管理
Spring基于AOP的事务管理 事务 事务是一系列动作,这一系列动作综合在一起组成一个完整的工作单元,如果有任何一个动作执行失败,那么事务 ...
- 学习AOP之透过Spring的Ioc理解Advisor
花了几天时间来学习Spring,突然明白一个问题,就是看书不能让人理解Spring,一方面要结合使用场景,另一方面要阅读源代码,这种方式理解起来事半功倍.那看书有什么用呢?主要还是扩展视野,毕竟书是别 ...
- 学习AOP之深入一点Spring Aop
上一篇<学习AOP之认识一下SpringAOP>中大体的了解了代理.动态代理及SpringAop的知识.因为写的篇幅长了点所以还是再写一篇吧.接下来开始深入一点Spring aop的一些实 ...
- 学习AOP之认识一下Spring AOP
心碎之事 要说知道AOP这个词倒是很久很久以前了,但是直到今天我也不敢说非常的理解它,其中的各种概念即抽象又太拗口. 在几次面试中都被问及AOP,但是真的没有答上来,或者都在面上,这给面试官的感觉就是 ...
- .Net中的AOP系列之构建一个汽车租赁应用
返回<.Net中的AOP>系列学习总目录 本篇目录 开始一个新项目 没有AOP的生活 变更的代价 使用AOP重构 本系列的源码本人已托管于Coding上:点击查看. 本系列的实验环境:VS ...
- .NET里简易实现AOP
.NET里简易实现AOP 前言 在MVC的过滤器章节中对于过滤器的使用就是AOP的一个实现了吧,时常在工作学习中遇到AOP对于它的运用可以说是很熟练了,就是没想过如果自己来实现的话是怎么实现的,性子比 ...
- 在.Net中实现自己的简易AOP
RealProxy基本代理类 RealProxy类提供代理的基本功能.这个类中有一个GetTransparentProxy方法,此方法返回当前代理实例的透明代理.这是我们AOP实现的主要依赖. 新建一 ...
- 使用Java原生代理实现AOP
### 本文由博主柒.原创,转载请注明出处 ### 完整源码下载地址 [https://github.com/MatrixSeven/JavaAOP](https://github.com/Matri ...
- 【开源】.Net Aop(静态织入)框架 BSF.Aop
BSF.Aop .Net 免费开源,静态Aop织入(直接修改IL中间语言)框架,类似PostSharp(收费): 实现前后Aop切面和INotifyPropertyChanged注入方式. 开源地址: ...
随机推荐
- git解决本地建立git仓库 连接远程git仓库出现拒绝合并问题
(git解决本地建立git仓库 连接远程git仓库出现拒绝合并问题) 第一步在本地创建仓库 在本地创建一个文件夹,cd 进入创建的文件夹之后 git init 创建仓库 ,ls -a 能够看到 .gi ...
- 如何让touchmove之后不触发touchend的事件
手机扫码看效果 不多说,直接上代码 <ul id="Ul"> <li>111</li> <li>222</li> < ...
- redis cluster info显示cluster_state:fail解决方案
1.查看错误信息: 1.1 错误信息(1) 127.0.0.1:7000> get name (error) CLUSTERDOWN The cluster is down 127.0.0.1: ...
- CSS之Bootstrap(快速布局)
简介 什么是Bootstrap? Bootstrap官网 框架:库 lib library jQuery作为一个框架来讲,提供一套比较便捷的操作DOM的方式 把大家都需要的功能预先写好到一些文件 这就 ...
- hihoCoder 1049 后序遍历 最详细的解题报告
题目来源:后序遍历 解题思路:开始时我只知道先通过先序.中序求出二叉树,然后再后序遍历二叉树,这当然也是一种解题思路,但是会做一些无用功,比如:计算二叉树.其实,可以直接通过先序序列和中序序列直接求出 ...
- WPF在.NET 5 中的线路图
WPF是用于构建Windows桌面应用程序的.NET Core UI框架.WPF的所属权最近已经移交给了我们的团队(Windows下开发生态系统和平台的团队).这种转变使跨UI框架(即WinUI和WP ...
- [Qt插件]-01Qt插件&&提升部件(自定义控件)
本篇的文档为:How to Create Qt Plugins https://doc.qt.io/qt-5/plugins-howto.html 前言 Qt插件(Qt Plugin)就是一个共享 ...
- 【week1错题集】
day9[2.f] # day9 题2.f ''' 有如下文件,t1.txt,里面的内容为: 葫芦娃,葫芦娃, 一根藤上七个瓜 风吹雨打,都不怕, 啦啦啦啦. 以r模式打开文件,从‘风吹雨打..... ...
- docker环境部署mysql
参考文档 docker官方:https://hub.docker.com/_/mysql/?tab=description 部署步骤 1. 拉取镜像 这里我拉取了tag为5.7的镜像 docker p ...
- final总结
final 1.类 不含任何子类,有父类(太监类):其中方法不能覆盖重写. 2.方法 最终方法,不能被覆盖重写. 3.局部变量 赋值后不能改变,只能赋一次值. 4.成员变量 <1>由于成员 ...