SpringBoot 之集成 Spring AOP

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。

在开始之前,我们先把需要的jar包添加到工程里。新增Maven依赖如下:

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-aop</artifactId>
  4. </dependency>

接下来,我们进入正题。这里的涉及的通知类型有:前置通知、后置最终通知、后置返回通知、后置异常通知、环绕通知,下面我们就具体的来看一下怎么在SpringBoot中添加这些通知。

 

 

首先我们先创建一个Aspect切面类:
 
  1. @Component
  2. @Aspect
  3. public class WebControllerAop {
  4. }
指定切点:
 
  1. //匹配com.zkn.learnspringboot.web.controller包及其子包下的所有类的所有方法
  2. @Pointcut("execution(* com.zkn.learnspringboot.web.controller..*.*(..))")
  3. public void executeService(){
  4. }

接着我们再创建一个Controller请求处理类:

 

 
  1. package com.zkn.learnspringboot.web.controller;
  2. import org.springframework.web.bind.annotation.RequestMapping;
  3. import org.springframework.web.bind.annotation.RestController;
  4. /**
  5. * Created by zkn on 2016/11/19.
  6. */
  7. @RestController
  8. @RequestMapping("/aop")
  9. public class AopTestController {
  10. }

 

前置通知

配置前置通知:
 
  1. /**
  2. * 前置通知,方法调用前被调用
  3. * @param joinPoint
  4. */
  5. @Before("executeService()")
  6. public void doBeforeAdvice(JoinPoint joinPoint){
  7. System.out.println("我是前置通知!!!");
  8. //获取目标方法的参数信息
  9. Object[] obj = joinPoint.getArgs();
  10. //AOP代理类的信息
  11. joinPoint.getThis();
  12. //代理的目标对象
  13. joinPoint.getTarget();
  14. //用的最多 通知的签名
  15. Signature signature = joinPoint.getSignature();
  16. //代理的是哪一个方法
  17. System.out.println(signature.getName());
  18. //AOP代理类的名字
  19. System.out.println(signature.getDeclaringTypeName());
  20. //AOP代理类的类(class)信息
  21. signature.getDeclaringType();
  22. //获取RequestAttributes
  23. RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
  24. //从获取RequestAttributes中获取HttpServletRequest的信息
  25. HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
  26. //如果要获取Session信息的话,可以这样写:
  27. //HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
  28. Enumeration<String> enumeration = request.getParameterNames();
  29. Map<String,String> parameterMap = Maps.newHashMap();
  30. while (enumeration.hasMoreElements()){
  31. String parameter = enumeration.nextElement();
  32. parameterMap.put(parameter,request.getParameter(parameter));
  33. }
  34. String str = JSON.toJSONString(parameterMap);
  35. if(obj.length > 0) {
  36. System.out.println("请求的参数信息为:"+str);
  37. }
  38. }
注意:这里用到了JoinPoint和RequestContextHolder。通过JoinPoint可以获得通知的签名信息,如目标方法名、目标方法参数信息等。通过RequestContextHolder来获取请求信息,Session信息。
接下来我们在Controller类里添加一个请求处理方法来测试一下前置通知:
 
  1. @RequestMapping("/testBeforeService.do")
  2. public String testBeforeService(String key,String value){
  3. return "key="+key+" value="+value;
  4. }
前置通知拦截结果如下所示:

后置返回通知

配置后置返回通知的代码如下:
 
  1. /**
  2. * 后置返回通知
  3. * 这里需要注意的是:
  4. * 如果参数中的第一个参数为JoinPoint,则第二个参数为返回值的信息
  5. * 如果参数中的第一个参数不为JoinPoint,则第一个参数为returning中对应的参数
  6. * returning 限定了只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知,否则不执行,对于returning对应的通知方法参数为Object类型将匹配任何目标返回值
  7. * @param joinPoint
  8. * @param keys
  9. */
  10. @AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys")
  11. public void doAfterReturningAdvice1(JoinPoint joinPoint,Object keys){
  12. System.out.println("第一个后置返回通知的返回值:"+keys);
  13. }
  14. @AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys",argNames = "keys")
  15. public void doAfterReturningAdvice2(String keys){
  16. System.out.println("第二个后置返回通知的返回值:"+keys);
  17. }
Controller里添加响应的请求处理信息来测试后置返回通知:
 
  1. @RequestMapping("/testAfterReturning.do")
  2. public String testAfterReturning(String key){
  3. return "key=: "+key;
  4. }
  5. @RequestMapping("/testAfterReturning01.do")
  6. public Integer testAfterReturning01(Integer key){
  7. return key;
  8. }
当发送请求为:http://localhost:8001/aop/testAfterReturning.do?key=testsss&value=855sss时,处理结果如图所示:
当发送请求为:http://localhost:8001/aop/testAfterReturning01.do?key=55553&value=855sss时,处理结果如图所示:

后置异常通知

后置异常通知的配置方式如下:
 
  1. /**
  2. * 后置异常通知
  3. * 定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法;
  4. * throwing 限定了只有目标方法抛出的异常与通知方法相应参数异常类型时才能执行后置异常通知,否则不执行,
  5. * 对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。
  6. * @param joinPoint
  7. * @param exception
  8. */
  9. @AfterThrowing(value = "executeService()",throwing = "exception")
  10. public void doAfterThrowingAdvice(JoinPoint joinPoint,Throwable exception){
  11. //目标方法名:
  12. System.out.println(joinPoint.getSignature().getName());
  13. if(exception instanceof NullPointerException){
  14. System.out.println("发生了空指针异常!!!!!");
  15. }
  16. }
Controller里配置响应的请求处理类:
 
  1. @RequestMapping("/testAfterThrowing.do")
  2. public String testAfterThrowing(String key){
  3. throw new NullPointerException();
  4. }
后置异常通知方法的处理结果如下所示:

后置最终通知

后置最终通知的配置方式如下:
 
  1. /**
  2. * 后置最终通知(目标方法只要执行完了就会执行后置通知方法)
  3. * @param joinPoint
  4. */
  5. @After("executeService()")
  6. public void doAfterAdvice(JoinPoint joinPoint){
  7. System.out.println("后置通知执行了!!!!");
  8. }
Controller类配置相应的请求处理类:
 
  1. @RequestMapping("/testAfter.do")
  2. public String testAfter(String key){
  3. throw new NullPointerException();
  4. }
  5. @RequestMapping("/testAfter02.do")
  6. public String testAfter02(String key){
  7. return key;
  8. }
当发送请求为:http://localhost:8001/aop/testAfter.do?key=55553&value=855sss

当发送请求为:http://localhost:8001/aop/testAfter02.do?key=55553&value=855sss

 

环绕通知

环绕通知的配置方式如下:
 
  1. /**
  2. * 环绕通知:
  3. * 环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。
  4. * 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
  5. */
  6. @Around("execution(* com.zkn.learnspringboot.web.controller..*.testAround*(..))")
  7. public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
  8. System.out.println("环绕通知的目标方法名:"+proceedingJoinPoint.getSignature().getName());
  9. try {
  10. Object obj = proceedingJoinPoint.proceed();
  11. return obj;
  12. } catch (Throwable throwable) {
  13. throwable.printStackTrace();
  14. }
  15. return null;
  16. }
Controller对应的请求处理类如下:
 
  1. @RequestMapping("/testAroundService.do")
  2. public String testAroundService(String key){
  3. return "环绕通知:"+key;
  4. }
当发送请求为:http://localhost:8001/aop/testAroundService.do?key=55553
当发送请求为:http://localhost:8001/aop/testAfter02.do?key=55553&value=855sss时,不符合环绕通知的切入规则,所以环绕通知不会 执行。
完整的AOP配置代码如下:
 
  1. package com.zkn.learnspringboot.aop;
  2. import com.alibaba.fastjson.JSON;
  3. import com.google.common.collect.Maps;
  4. import org.aspectj.lang.JoinPoint;
  5. import org.aspectj.lang.ProceedingJoinPoint;
  6. import org.aspectj.lang.Signature;
  7. import org.aspectj.lang.annotation.*;
  8. import org.springframework.stereotype.Component;
  9. import org.springframework.web.context.request.RequestAttributes;
  10. import org.springframework.web.context.request.RequestContextHolder;
  11. import javax.servlet.http.HttpServletRequest;
  12. import javax.servlet.http.HttpSession;
  13. import java.util.Enumeration;
  14. import java.util.Map;
  15. /**
  16. * Created by zkn on 2016/11/18.
  17. */
  18. @Component
  19. @Aspect
  20. public class WebControllerAop {
  21. //匹配com.zkn.learnspringboot.web.controller包及其子包下的所有类的所有方法
  22. @Pointcut("execution(* com.zkn.learnspringboot.web.controller..*.*(..))")
  23. public void executeService(){
  24. }
  25. /**
  26. * 前置通知,方法调用前被调用
  27. * @param joinPoint
  28. */
  29. @Before("executeService()")
  30. public void doBeforeAdvice(JoinPoint joinPoint){
  31. System.out.println("我是前置通知!!!");
  32. //获取目标方法的参数信息
  33. Object[] obj = joinPoint.getArgs();
  34. //AOP代理类的信息
  35. joinPoint.getThis();
  36. //代理的目标对象
  37. joinPoint.getTarget();
  38. //用的最多 通知的签名
  39. Signature signature = joinPoint.getSignature();
  40. //代理的是哪一个方法
  41. System.out.println(signature.getName());
  42. //AOP代理类的名字
  43. System.out.println(signature.getDeclaringTypeName());
  44. //AOP代理类的类(class)信息
  45. signature.getDeclaringType();
  46. //获取RequestAttributes
  47. RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
  48. //从获取RequestAttributes中获取HttpServletRequest的信息
  49. HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
  50. //如果要获取Session信息的话,可以这样写:
  51. //HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
  52. Enumeration<String> enumeration = request.getParameterNames();
  53. Map<String,String> parameterMap = Maps.newHashMap();
  54. while (enumeration.hasMoreElements()){
  55. String parameter = enumeration.nextElement();
  56. parameterMap.put(parameter,request.getParameter(parameter));
  57. }
  58. String str = JSON.toJSONString(parameterMap);
  59. if(obj.length > 0) {
  60. System.out.println("请求的参数信息为:"+str);
  61. }
  62. }
  63. /**
  64. * 后置返回通知
  65. * 这里需要注意的是:
  66. * 如果参数中的第一个参数为JoinPoint,则第二个参数为返回值的信息
  67. * 如果参数中的第一个参数不为JoinPoint,则第一个参数为returning中对应的参数
  68. * returning 限定了只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知,否则不执行,对于returning对应的通知方法参数为Object类型将匹配任何目标返回值
  69. * @param joinPoint
  70. * @param keys
  71. */
  72. @AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys")
  73. public void doAfterReturningAdvice1(JoinPoint joinPoint,Object keys){
  74. System.out.println("第一个后置返回通知的返回值:"+keys);
  75. }
  76. @AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys",argNames = "keys")
  77. public void doAfterReturningAdvice2(String keys){
  78. System.out.println("第二个后置返回通知的返回值:"+keys);
  79. }
  80. /**
  81. * 后置异常通知
  82. * 定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法;
  83. * throwing 限定了只有目标方法抛出的异常与通知方法相应参数异常类型时才能执行后置异常通知,否则不执行,
  84. * 对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。
  85. * @param joinPoint
  86. * @param exception
  87. */
  88. @AfterThrowing(value = "executeService()",throwing = "exception")
  89. public void doAfterThrowingAdvice(JoinPoint joinPoint,Throwable exception){
  90. //目标方法名:
  91. System.out.println(joinPoint.getSignature().getName());
  92. if(exception instanceof NullPointerException){
  93. System.out.println("发生了空指针异常!!!!!");
  94. }
  95. }
  96. /**
  97. * 后置最终通知(目标方法只要执行完了就会执行后置通知方法)
  98. * @param joinPoint
  99. */
  100. @After("executeService()")
  101. public void doAfterAdvice(JoinPoint joinPoint){
  102. System.out.println("后置通知执行了!!!!");
  103. }
  104. /**
  105. * 环绕通知:
  106. * 环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。
  107. * 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
  108. */
  109. @Around("execution(* com.zkn.learnspringboot.web.controller..*.testAround*(..))")
  110. public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
  111. System.out.println("环绕通知的目标方法名:"+proceedingJoinPoint.getSignature().getName());
  112. try {//obj之前可以写目标方法执行前的逻辑
  113. Object obj = proceedingJoinPoint.proceed();//调用执行目标方法
  114. return obj;
  115. } catch (Throwable throwable) {
  116. throwable.printStackTrace();
  117. }
  118. return null;
  119. }
  120. }
完整的Controller类代码如下:
 
  1. package com.zkn.learnspringboot.web.controller;
  2. import org.springframework.web.bind.annotation.RequestMapping;
  3. import org.springframework.web.bind.annotation.RestController;
  4. /**
  5. * Created by zkn on 2016/11/19.
  6. */
  7. @RestController
  8. @RequestMapping("/aop")
  9. public class AopTestController {
  10. @RequestMapping("/testBeforeService.do")
  11. public String testBeforeService(String key,String value){
  12. return "key="+key+" value="+value;
  13. }
  14. @RequestMapping("/testAfterReturning.do")
  15. public String testAfterReturning(String key){
  16. return "key=: "+key;
  17. }
  18. @RequestMapping("/testAfterReturning01.do")
  19. public Integer testAfterReturning01(Integer key){
  20. return key;
  21. }
  22. @RequestMapping("/testAfterThrowing.do")
  23. public String testAfterThrowing(String key){
  24. throw new NullPointerException();
  25. }
  26. @RequestMapping("/testAfter.do")
  27. public String testAfter(String key){
  28. throw new NullPointerException();
  29. }
  30. @RequestMapping("/testAfter02.do")
  31. public String testAfter02(String key){
  32. return key;
  33. }
  34. @RequestMapping("/testAroundService.do")
  35. public String testAroundService(String key){
  36. return "环绕通知:"+key;
  37. }
  38. }

代码地址: https://github.com/zhangconan/LearnSpringBoot/tree/master/src/main/java/com/zkn/learnspringboot/aop 

转自:https://blog.csdn.net/zknxx/article/details/53240959

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/448988.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

9件事把你从消极情绪中解救出来

也许你很难相信&#xff0c;但是情绪可以通过重复形成习惯。消极情绪甚至可以变成某种嵌入你每日生活的东西。 如何将它们赶跑? 你发现你不断地埋怨世界和自己?你可以轻易地生气并且对人变得刻薄?那愤怒又是否成为你对事情本能的回应了?如果你对所述问题中的一个回答了“是…

数据库主键自增插入显示值

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主同意不得转载。 https://blog.csdn.net/nwsuaf2009012882/article/details/32703597 SQL Server 2008 数据库主键自增插入显示值 前几天在工作的时候遇到在删除数据库中表的数据的时候。删除之后&#xff0c;又一次…

解决: This application has no explicit mapping for /error, so you are seeing this as a fallback.

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 报错如题&#xff0c;出现这个异常说明了跳转页面的url无对应的值. 原因1: Application启动类的位置不对.要将Application类放在最外侧…

Selenium自动化获取WebSocket信息

性能日志 ChromeDriver支持性能日志记录&#xff0c;您可以从中获取域“时间轴”&#xff0c;“网络”和“页面”的事件&#xff0c;以及指定跟踪类别的跟踪数据。启用性能日志 默认情况下不启用性能日志记录。因此&#xff0c;在创建新会话时&#xff0c;您必须启用它。 Desir…

零负债之人的10个习惯

无论你是已下定决心要于今年实现零负债&#xff0c;还是距离这个目标的实现有很长的路要走&#xff0c;能受到启发总是好事。 看看你认识的已经过上“无债一身轻”生活的人──朋友、家人、同事或是你认为可能与其他无负债之人具有类似品质的人。 下文为无负债之人的10个共同…

《App后台开发运维与架构实践》第3章 App后台核心技术

2019独角兽企业重金招聘Python工程师标准>>> 3.1 用户验证方案 3.1.1 使用HTTPS协议 HTTPS协议是“HTTP协议”和“SSL/TLS”的组合。SSL&#xff08;Secure Sockets Layer&#xff09;&#xff0c;即安全套接层&#xff0c;是为了解决因HTTP协议是明文而导致传输内容…

IntelliJ IDEA 配置 JDK

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 提前安装jdk&#xff0c;配置环境变量 一、配置jdk 1、依次点开File -->Project Structure&#xff0c;点击左侧标签页&#xff0c…

xml编辑无提示?这么破!

在学习testng这个单元测试框架时&#xff0c;如果咱们碰到了编辑测试套件xml&#xff0c;不提示的情况&#xff08;有提示方便咱们学习&#xff0c;并且testng的测试套件定义必须按照他的dtd文件约束来&#xff09;&#xff0c;咱们可以按照下面的步骤去解决这个问题。 1.检查t…

“云栖直播”升级为“公开课”

直播平台是面向广大开发者的视频学习平台&#xff0c;帮助广大开发者学习最新技术&#xff0c;了解最新阿里云产品以及最新技术发展趋势&#xff0c;帮助开发者们不断学习与成长。截止到2019年3月&#xff0c;直播共进行800余场&#xff0c;观看人次100万。  社区将对“云栖直…

遭银行账号诈骗最快最有效自救法

银行卡或账户诈骗案件层出不穷&#xff0c;当汇错款时该怎么做&#xff0c;切记以下方法&#xff1a; 一、当汇错款或被骗汇款后&#xff0c;最快最有效的紧急自救法&#xff1a;当你把自己的钱不小心汇到了不该汇的人卡上&#xff0c;或者被骗子忽悠而把钱汇给了骗子&#xf…

SQL 判断非空 NULL :IFNUL( ) 、COALESCE( ) 、ISNULL( ) 、NVL( )

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. mysql 支持&#xff1a; IFNULL&#xff08;&#xff09;、COALESCE&#xff08;&#xff09; 如 IFNULL(UnitsOnOrder, 0) 或者 CO…

navigator.geolocation的应用 - 将定位信息显示在百度地图上

在学习navigator.geolocation的时候&#xff0c;有一个实例是获取坐标后显示在谷歌地图上。众所周知&#xff0c;谷歌地图国内并不能直接访问&#xff0c;得用特殊手段&#xff0c;那我要测试的时候还要开着梯子挺麻烦的&#xff0c;想给别人用也得那个人能访问谷歌地图先。 地…

centos7 mysql数据库安装和配置

2019独角兽企业重金招聘Python工程师标准>>> 一、系统环境 yum update升级以后的系统版本为 [rootyl-web yl]# cat /etc/redhat-release CentOS Linux release 7.1.1503 (Core) 二、mysql安装 一般网上给出的资料都是 #yum install mysql #yum install mysql-serve…

5种聪明工作法

1、每天最多做三件事 请拿出你落落长的待办清单&#xff0c;圈出最重要的一~三件事&#xff0c;然后给自己一天的时间&#xff0c;卯足全力解决它! 你不需要因为还有很多事要做而焦虑&#xff0c;只需要专注今天、当下、以及最重要的问题。 《与成功有约》作者史蒂芬.柯维(Step…

【Quartz】Quartz概述及入门实例

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Quartz 在开源任务调度框架中的翘首&#xff0c;它提供了强大任务调度机制&#xff0c;难能可贵的是它同时保持了使用的简单性。Quartz 允…

python中del语句

有一种方式可以从列表按照给定的索引而不是值来移除一个元素: 那就是 del 语句。 它不同于会返回一个值的 pop() 方法。 del 语句也可以用来从列表中移除切片或者清空整个python列表&#xff08;我们之前用过的方式是将一个空列表赋值给指定的切片&#xff09;。 例如: >>…

偷时间的孩子

从事临床心理工作已有十三、四年(至一九九五年)&#xff0c;真的有很多话想跟父母们敞开心扉的谈谈。 忙碌的现代社会&#xff0c;让我窥探到了许许多多的杰出角色&#xff0c;他们偷取家庭时间去换取自己的功成名就&#xff0c;他们的心随着公司的企划案四处流浪&#xff0c;孩…

关于openstack 专业博主地址.后续更新

首先官方文档要放的https://docs.openstack.org/ 关于导入镜像方面说的很详细的.https://www.cnblogs.com/liawne/p/9322221.html 每天5分钟系列,有docker openstack等,而且还出书了.https://www.cnblogs.com/CloudMan6/p/5384923.html 转载于:https://www.cnblogs.com/lovesKe…

Java第一章java语言的概述

一、java语言的概述&#xff1a; 1.1dos命令 常用的dos命令&#xff1a; dir&#xff1a;列出当前目录下的文件以及文件夹 md&#xff1a;创建目录 rd&#xff1a;删除目录 cd&#xff1a;进入指定目录 cd..&#xff1a;退回到上一级目录 cd\&#xff1a;退回到根目录 del&…

【Quartz】深入Job、JobDetail、JobDataMap、Trigger

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Quartz API核心接口有&#xff1a; Scheduler – 与scheduler交互的主要API&#xff1b;Job – 你通过scheduler执行任务&#xff0c;你…