一大早,小王就急匆匆的跑过来找我,说:周哥,那个记录日志的功能我想请教一下。

因为公司某个项目要跟别的平台做对接,我们这边需要给他们提供一套接口。昨天,我就将记录接口日志的工作安排给了小王。

下面是我跟小王的主要对话。

我:说说怎么了?

小王:我将记录接口日志的功能放到了每个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吗?的更多相关文章

  1. 基于spring注解AOP的异常处理

    一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...fin ...

  2. Spring基于AOP的事务管理

                                  Spring基于AOP的事务管理 事务 事务是一系列动作,这一系列动作综合在一起组成一个完整的工作单元,如果有任何一个动作执行失败,那么事务 ...

  3. 学习AOP之透过Spring的Ioc理解Advisor

    花了几天时间来学习Spring,突然明白一个问题,就是看书不能让人理解Spring,一方面要结合使用场景,另一方面要阅读源代码,这种方式理解起来事半功倍.那看书有什么用呢?主要还是扩展视野,毕竟书是别 ...

  4. 学习AOP之深入一点Spring Aop

    上一篇<学习AOP之认识一下SpringAOP>中大体的了解了代理.动态代理及SpringAop的知识.因为写的篇幅长了点所以还是再写一篇吧.接下来开始深入一点Spring aop的一些实 ...

  5. 学习AOP之认识一下Spring AOP

    心碎之事 要说知道AOP这个词倒是很久很久以前了,但是直到今天我也不敢说非常的理解它,其中的各种概念即抽象又太拗口. 在几次面试中都被问及AOP,但是真的没有答上来,或者都在面上,这给面试官的感觉就是 ...

  6. .Net中的AOP系列之构建一个汽车租赁应用

    返回<.Net中的AOP>系列学习总目录 本篇目录 开始一个新项目 没有AOP的生活 变更的代价 使用AOP重构 本系列的源码本人已托管于Coding上:点击查看. 本系列的实验环境:VS ...

  7. .NET里简易实现AOP

    .NET里简易实现AOP 前言 在MVC的过滤器章节中对于过滤器的使用就是AOP的一个实现了吧,时常在工作学习中遇到AOP对于它的运用可以说是很熟练了,就是没想过如果自己来实现的话是怎么实现的,性子比 ...

  8. 在.Net中实现自己的简易AOP

    RealProxy基本代理类 RealProxy类提供代理的基本功能.这个类中有一个GetTransparentProxy方法,此方法返回当前代理实例的透明代理.这是我们AOP实现的主要依赖. 新建一 ...

  9. 使用Java原生代理实现AOP

    ### 本文由博主柒.原创,转载请注明出处 ### 完整源码下载地址 [https://github.com/MatrixSeven/JavaAOP](https://github.com/Matri ...

  10. 【开源】.Net Aop(静态织入)框架 BSF.Aop

    BSF.Aop .Net 免费开源,静态Aop织入(直接修改IL中间语言)框架,类似PostSharp(收费): 实现前后Aop切面和INotifyPropertyChanged注入方式. 开源地址: ...

随机推荐

  1. web 部署专题(三):压力测试(一)工具 siege

    1.介绍 Siege是一个压力测试和评测工具,设计用于WEB开发这评估应用在压力下的承受能力:可以根据配置对一个WEB站点进行多用户的并发访问,记录每个用户所有请求过程的相应时间,并在一定数量的并发访 ...

  2. java 基本语法(六) 流程控制(三) 关键字:break和continue

  3. 基于animate.css动画库的全屏滚动小插件,适用于vue.js(移动端、pc)项目

    功能简介 基于animate.css动画库的全屏滚动,适用于vue.js(移动端.pc)项目. 安装 npm install vue-animate-fullpage --save 使用 main.j ...

  4. SpringBoot2.x入门:使用CommandLineRunner钩子接口

    前提 这篇文章是<SpringBoot2.x入门>专辑的第6篇文章,使用的SpringBoot版本为2.3.1.RELEASE,JDK版本为1.8. 这篇文章主要简单聊聊钩子接口Comma ...

  5. js 分享QQ、QQ空间、微信、微博

    //分享QQ好友 function qq(title,url,pic) { var p = { url: 'http://test.qicheyitiao.com',/*获取URL,可加上来自分享到Q ...

  6. 为什么阿里、头条、美团这些互联网大厂都在用Spring Boot?

    前言 自 2014 年发布至今,Spring Boot 的搜索指数 一路飙升.没错 Spring Boot 越来越火了,作为一名行走一线的 Java 程序员,你可能在各个方面感受到了 Spring B ...

  7. 三、Python系列——Pandas数据库读取数据

    Pandas主要先读取表格类型的数据,然后进行分析. import pandas as pd# 由于是用pandas模块操作数据,因此不用在路径前加open,否则就是python直接打开文件,可能还会 ...

  8. centos7.6静默安装oracle 11G RAC

    环境介绍, esxi6.0 ,VMware vSphere Client6.0 linux 版本Centos7.6(最小化安装) Oracle 版本 oracle 11g 11.2.0.4 虚拟化环境 ...

  9. echarts 实战 : 标题的富文本样式

    官方文档在这一块交待的不是很清楚,记录一下. title:{ left:15, top:10, subtext:"AAA {yellow|316} BBB {blue|219}", ...

  10. python元编程(metaclass)

    Python元编程就是使用metaclass技术进行编程,99%的情况下不会使用,了解即可. Python中的类和对象 对于学习Python和使用Python的同学,你是否好奇过Python中的对象究 ...