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,一经查实,立即删除!

相关文章

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

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

Selenium自动化获取WebSocket信息

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

《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…

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…

【Quartz】Quartz概述及入门实例

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

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

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

图形界面上机作业

1、 制作一个如图所示的界面&#xff08;使用FlowLayout布局&#xff09;&#xff0c;不要求实现功能。 2、设计一个用标签、文本行与按钮来登录的界面&#xff08;用GridLayout布局方式&#xff09;。如图所示。 转载于:https://www.cnblogs.com/quan-2723365710/p/10881691.h…

【Quartz】Spring3.2.9 + Quqrtz2.2.1 实现定时实例

一、工程创建 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1、新建一个工程&#xff0c;导入相应的包Spring3.2.9Quqrtz2.2.1commons-logging 集成起来比较简单,对线程无需任何理解&a…

第十二周作业

这个作业属于那个课程c语言这个作业要求在哪里https://edu.cnblogs.com/campus/zswxy/computer-scienceclass4-2018/homework/3236我在这个课程的目标是学习掌握单向链表&#xff0c;掌握二级指针的概念&#xff0c;以及指针数组这个作业在哪个具体方面帮助我实现目标前面3道题…

【Quartz】插件的使用

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Quartz 框架提供了几种用于扩展平台能力的方式。通过使用各种 "钩子" (通常指的就是扩展点)&#xff0c;Quartz 变得很容易被扩…

自动化运维平台(前端vue)

前端的大体流程&#xff1a;首先是Login登录组件&#xff0c;当输入用户名和密码之后&#xff0c;发送post请求到后端&#xff0c;然后根据返回的数据的是否正常&#xff0c;如果正常&#xff0c;将返回的token以及用户名保存到sessionStorage中&#xff0c;并使用导航守卫进行…

Quartz 之入门示例

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 环境:XPMyeclipse6.5JDK1.6 quartz官网:http://www.quartz-scheduler.org/ 参考资料 1 Quartz任务调度快速入门 http://www.blogjava…

CSS3最颠覆性的动画效果,基本属性[3D]

和2D一样也是transform 即变形 1)rotateX rotateY rotateZ&#xff08;也可以用transform-origin来设置旋转中心点&#xff09; 2)透视(perspective) 给父亲加透视&#xff0c;透视就是模拟眼睛到物体的距离&#xff0c;近大远小&#xff0c;即数值越小&#xff0c;3D越明显 理…

解决报错 :A component required a bean of type ‘gentle.test.Show‘ that could not be found

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 启动工程失败&#xff0c;报错如题&#xff1a; A component required a bean of type gentle.test.Show that could not be found.…

解决.quartz.ObjectAlreadyExistsException: Unable to store Job : ‘jyGroup.jyJob‘, because one already

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 报错如题&#xff1a; 定时任务出现异常 &#xff1a; org.quartz.ObjectAlreadyExistsException: Unable to store Job : jyGroup.…

WeMos-D1R2的使用

2019独角兽企业重金招聘Python工程师标准>>> WeMos介绍 WeMos-D1R2一个基于ESP8266-12 Wifi模块的Arduino-UNO开发板。也就是说&#xff0c;WeMos-D1R2是一个具有wifi功能的Arduino开发板&#xff0c;但WeMos-D1R2与Arduino-UNO的引脚不是一一对应的&#xff0c;其对…

RabbitMQ MQTT协议和AMQP协议

RabbitMQ MQTT协议和AMQP协议 1 序言... 1 1.1 RabbitMq结构... 1 1.2 RabbitMq消息接收... 4 1.3 Exchange种类和消息发送模式... 4 1.4 RabbitMq的协议... 6 1.4.1 AMQP协议... 6 1.4.2 MQTT协议... 8 2 RabbitMq服务器安装和使用…