SpringBoot 之集成 Spring AOP
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。
在开始之前,我们先把需要的jar包添加到工程里。新增Maven依赖如下:
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-aop</artifactId>
- </dependency>
接下来,我们进入正题。这里的涉及的通知类型有:前置通知、后置最终通知、后置返回通知、后置异常通知、环绕通知,下面我们就具体的来看一下怎么在SpringBoot中添加这些通知。
- @Component
- @Aspect
- public class WebControllerAop {
- }
指定切点:
- //匹配com.zkn.learnspringboot.web.controller包及其子包下的所有类的所有方法
- @Pointcut("execution(* com.zkn.learnspringboot.web.controller..*.*(..))")
- public void executeService(){
- }
接着我们再创建一个Controller请求处理类:
- package com.zkn.learnspringboot.web.controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- /**
- * Created by zkn on 2016/11/19.
- */
- @RestController
- @RequestMapping("/aop")
- public class AopTestController {
- }
前置通知
- /**
- * 前置通知,方法调用前被调用
- * @param joinPoint
- */
- @Before("executeService()")
- public void doBeforeAdvice(JoinPoint joinPoint){
- System.out.println("我是前置通知!!!");
- //获取目标方法的参数信息
- Object[] obj = joinPoint.getArgs();
- //AOP代理类的信息
- joinPoint.getThis();
- //代理的目标对象
- joinPoint.getTarget();
- //用的最多 通知的签名
- Signature signature = joinPoint.getSignature();
- //代理的是哪一个方法
- System.out.println(signature.getName());
- //AOP代理类的名字
- System.out.println(signature.getDeclaringTypeName());
- //AOP代理类的类(class)信息
- signature.getDeclaringType();
- //获取RequestAttributes
- RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
- //从获取RequestAttributes中获取HttpServletRequest的信息
- HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
- //如果要获取Session信息的话,可以这样写:
- //HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
- Enumeration<String> enumeration = request.getParameterNames();
- Map<String,String> parameterMap = Maps.newHashMap();
- while (enumeration.hasMoreElements()){
- String parameter = enumeration.nextElement();
- parameterMap.put(parameter,request.getParameter(parameter));
- }
- String str = JSON.toJSONString(parameterMap);
- if(obj.length > 0) {
- System.out.println("请求的参数信息为:"+str);
- }
- }
注意:这里用到了JoinPoint和RequestContextHolder。通过JoinPoint可以获得通知的签名信息,如目标方法名、目标方法参数信息等。通过RequestContextHolder来获取请求信息,Session信息。
- @RequestMapping("/testBeforeService.do")
- public String testBeforeService(String key,String value){
- return "key="+key+" value="+value;
- }
前置通知拦截结果如下所示:
后置返回通知
配置后置返回通知的代码如下:
- /**
- * 后置返回通知
- * 这里需要注意的是:
- * 如果参数中的第一个参数为JoinPoint,则第二个参数为返回值的信息
- * 如果参数中的第一个参数不为JoinPoint,则第一个参数为returning中对应的参数
- * returning 限定了只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知,否则不执行,对于returning对应的通知方法参数为Object类型将匹配任何目标返回值
- * @param joinPoint
- * @param keys
- */
- @AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys")
- public void doAfterReturningAdvice1(JoinPoint joinPoint,Object keys){
- System.out.println("第一个后置返回通知的返回值:"+keys);
- }
- @AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys",argNames = "keys")
- public void doAfterReturningAdvice2(String keys){
- System.out.println("第二个后置返回通知的返回值:"+keys);
- }
Controller里添加响应的请求处理信息来测试后置返回通知:
- @RequestMapping("/testAfterReturning.do")
- public String testAfterReturning(String key){
- return "key=: "+key;
- }
- @RequestMapping("/testAfterReturning01.do")
- public Integer testAfterReturning01(Integer key){
- return key;
- }
当发送请求为:http://localhost:8001/aop/testAfterReturning.do?key=testsss&value=855sss时,处理结果如图所示:
后置异常通知
- /**
- * 后置异常通知
- * 定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法;
- * throwing 限定了只有目标方法抛出的异常与通知方法相应参数异常类型时才能执行后置异常通知,否则不执行,
- * 对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。
- * @param joinPoint
- * @param exception
- */
- @AfterThrowing(value = "executeService()",throwing = "exception")
- public void doAfterThrowingAdvice(JoinPoint joinPoint,Throwable exception){
- //目标方法名:
- System.out.println(joinPoint.getSignature().getName());
- if(exception instanceof NullPointerException){
- System.out.println("发生了空指针异常!!!!!");
- }
- }
Controller里配置响应的请求处理类:
- @RequestMapping("/testAfterThrowing.do")
- public String testAfterThrowing(String key){
- throw new NullPointerException();
- }
后置异常通知方法的处理结果如下所示:
后置最终通知
- /**
- * 后置最终通知(目标方法只要执行完了就会执行后置通知方法)
- * @param joinPoint
- */
- @After("executeService()")
- public void doAfterAdvice(JoinPoint joinPoint){
- System.out.println("后置通知执行了!!!!");
- }
Controller类配置相应的请求处理类:
- @RequestMapping("/testAfter.do")
- public String testAfter(String key){
- throw new NullPointerException();
- }
- @RequestMapping("/testAfter02.do")
- public String testAfter02(String key){
- return key;
- }
当发送请求为:http://localhost:8001/aop/testAfter.do?key=55553&value=855sss
当发送请求为:http://localhost:8001/aop/testAfter02.do?key=55553&value=855sss
环绕通知
- /**
- * 环绕通知:
- * 环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。
- * 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
- */
- @Around("execution(* com.zkn.learnspringboot.web.controller..*.testAround*(..))")
- public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
- System.out.println("环绕通知的目标方法名:"+proceedingJoinPoint.getSignature().getName());
- try {
- Object obj = proceedingJoinPoint.proceed();
- return obj;
- } catch (Throwable throwable) {
- throwable.printStackTrace();
- }
- return null;
- }
- @RequestMapping("/testAroundService.do")
- public String testAroundService(String key){
- return "环绕通知:"+key;
- }
当发送请求为:http://localhost:8001/aop/testAroundService.do?key=55553
- package com.zkn.learnspringboot.aop;
- import com.alibaba.fastjson.JSON;
- import com.google.common.collect.Maps;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.Signature;
- import org.aspectj.lang.annotation.*;
- import org.springframework.stereotype.Component;
- import org.springframework.web.context.request.RequestAttributes;
- import org.springframework.web.context.request.RequestContextHolder;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpSession;
- import java.util.Enumeration;
- import java.util.Map;
- /**
- * Created by zkn on 2016/11/18.
- */
- @Component
- @Aspect
- public class WebControllerAop {
- //匹配com.zkn.learnspringboot.web.controller包及其子包下的所有类的所有方法
- @Pointcut("execution(* com.zkn.learnspringboot.web.controller..*.*(..))")
- public void executeService(){
- }
- /**
- * 前置通知,方法调用前被调用
- * @param joinPoint
- */
- @Before("executeService()")
- public void doBeforeAdvice(JoinPoint joinPoint){
- System.out.println("我是前置通知!!!");
- //获取目标方法的参数信息
- Object[] obj = joinPoint.getArgs();
- //AOP代理类的信息
- joinPoint.getThis();
- //代理的目标对象
- joinPoint.getTarget();
- //用的最多 通知的签名
- Signature signature = joinPoint.getSignature();
- //代理的是哪一个方法
- System.out.println(signature.getName());
- //AOP代理类的名字
- System.out.println(signature.getDeclaringTypeName());
- //AOP代理类的类(class)信息
- signature.getDeclaringType();
- //获取RequestAttributes
- RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
- //从获取RequestAttributes中获取HttpServletRequest的信息
- HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
- //如果要获取Session信息的话,可以这样写:
- //HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
- Enumeration<String> enumeration = request.getParameterNames();
- Map<String,String> parameterMap = Maps.newHashMap();
- while (enumeration.hasMoreElements()){
- String parameter = enumeration.nextElement();
- parameterMap.put(parameter,request.getParameter(parameter));
- }
- String str = JSON.toJSONString(parameterMap);
- if(obj.length > 0) {
- System.out.println("请求的参数信息为:"+str);
- }
- }
- /**
- * 后置返回通知
- * 这里需要注意的是:
- * 如果参数中的第一个参数为JoinPoint,则第二个参数为返回值的信息
- * 如果参数中的第一个参数不为JoinPoint,则第一个参数为returning中对应的参数
- * returning 限定了只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知,否则不执行,对于returning对应的通知方法参数为Object类型将匹配任何目标返回值
- * @param joinPoint
- * @param keys
- */
- @AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys")
- public void doAfterReturningAdvice1(JoinPoint joinPoint,Object keys){
- System.out.println("第一个后置返回通知的返回值:"+keys);
- }
- @AfterReturning(value = "execution(* com.zkn.learnspringboot.web.controller..*.*(..))",returning = "keys",argNames = "keys")
- public void doAfterReturningAdvice2(String keys){
- System.out.println("第二个后置返回通知的返回值:"+keys);
- }
- /**
- * 后置异常通知
- * 定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法;
- * throwing 限定了只有目标方法抛出的异常与通知方法相应参数异常类型时才能执行后置异常通知,否则不执行,
- * 对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。
- * @param joinPoint
- * @param exception
- */
- @AfterThrowing(value = "executeService()",throwing = "exception")
- public void doAfterThrowingAdvice(JoinPoint joinPoint,Throwable exception){
- //目标方法名:
- System.out.println(joinPoint.getSignature().getName());
- if(exception instanceof NullPointerException){
- System.out.println("发生了空指针异常!!!!!");
- }
- }
- /**
- * 后置最终通知(目标方法只要执行完了就会执行后置通知方法)
- * @param joinPoint
- */
- @After("executeService()")
- public void doAfterAdvice(JoinPoint joinPoint){
- System.out.println("后置通知执行了!!!!");
- }
- /**
- * 环绕通知:
- * 环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。
- * 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
- */
- @Around("execution(* com.zkn.learnspringboot.web.controller..*.testAround*(..))")
- public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
- System.out.println("环绕通知的目标方法名:"+proceedingJoinPoint.getSignature().getName());
- try {//obj之前可以写目标方法执行前的逻辑
- Object obj = proceedingJoinPoint.proceed();//调用执行目标方法
- return obj;
- } catch (Throwable throwable) {
- throwable.printStackTrace();
- }
- return null;
- }
- }
完整的Controller类代码如下:
- package com.zkn.learnspringboot.web.controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- /**
- * Created by zkn on 2016/11/19.
- */
- @RestController
- @RequestMapping("/aop")
- public class AopTestController {
- @RequestMapping("/testBeforeService.do")
- public String testBeforeService(String key,String value){
- return "key="+key+" value="+value;
- }
- @RequestMapping("/testAfterReturning.do")
- public String testAfterReturning(String key){
- return "key=: "+key;
- }
- @RequestMapping("/testAfterReturning01.do")
- public Integer testAfterReturning01(Integer key){
- return key;
- }
- @RequestMapping("/testAfterThrowing.do")
- public String testAfterThrowing(String key){
- throw new NullPointerException();
- }
- @RequestMapping("/testAfter.do")
- public String testAfter(String key){
- throw new NullPointerException();
- }
- @RequestMapping("/testAfter02.do")
- public String testAfter02(String key){
- return key;
- }
- @RequestMapping("/testAroundService.do")
- public String testAroundService(String key){
- return "环绕通知:"+key;
- }
- }
代码地址: https://github.com/zhangconan/LearnSpringBoot/tree/master/src/main/java/com/zkn/learnspringboot/aop
转自:https://blog.csdn.net/zknxx/article/details/53240959
SpringBoot 之集成 Spring AOP相关推荐
- Spring-Boot (四) 集成Spring Security
为什么80%的码农都做不了架构师?>>> http://nealma.com/2016/04/30/spring-boot-4-security/ ### 前言 shi ...
- springboot下的spring aop注解实现和execution正则实现
先上maven依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId> ...
- SpringBoot集成Spring Security(一)登录注销
同个人网站 https://www.serendipper-x.cn/,欢迎访问 ! SpringBoot集成Spring Security(二)注册 .密码加密.修改密码 写在前面 Spring S ...
- SpringBoot 框架中 使用Spring Aop 、创建注解、创建枚举类 使用过程记录
1.开始 在Springboot框架中引入AOP <dependency><groupId>org.springframework.boot</groupId>&l ...
- spring Aop实现身份验证和springboot异常统一处理
文章有不当之处,欢迎指正,如果喜欢微信阅读,你也可以关注我的微信公众号:好好学java,获取优质学习资源. 一.spring Aop身份验证 一般,如果用户没有登录的话,用户只可以查看商品,但是其他的 ...
- SpringBoot集成Spring Security —— 第二章自动登录
文章目录 一.修改login.html 二.两种实现方式 2.1 Cookie 存储 2.2 数据库存储 2.2.1 基本原理 2.2.2 代码实现 三.运行程序 在上一章:SpringBoot集成S ...
- SpringBoot集成Spring Security(二)注册 、密码加密、修改密码
SpringBoot集成Spring Security(一)登录注销 写在前面 上一节创建了项目并且利用Spring Security完成了登录注销功能,这里继续说一下注册.密码加密和找回密码,代码注 ...
- springboot security 权限校验_十二、SpringBoot 优雅的集成Spring Security
前言 至于什么是Spring security ,主要两个作用,用户认证和授权.即我们常说的,用户只有登录了才能进行其他操作,没有登录的话就重定向到登录界面.有的用户有权限执行某一操作,而有的用户不能 ...
- SpringBoot中AOP实现落地——Filter(过滤器)、Intercepter(拦截器)、Aspect(Spring AOP)
文章目录 一.一切要从Servlet说起 1.1什么是Servlet 1.2为什么需要Servlet 1.3Servlet如何响应用户请求 1.4Servlet与Tomcat处理请求的流程 1.5Se ...
最新文章
- oracle 只读同名词,Oracle创建只读用户,授予视图/同义词/会话权限
- 嵌入式MVN指令解析
- 浅析 React Fiber
- SAP Spartacus默认的货币列表currency是从源代码什么地方读取的
- web前端开发面试题(答案)
- --专访雷果国: 从1.5K到18K 一个程序员的5年成长之路--
- 经历越多困难,你就变的更韧性
- java g1的并行_Java 11好用吗
- Ubuntu Gitosis安装设置
- windows电脑自动安装第三方软件-联想客服建议解决办法
- 腾讯地图获取经纬度 Java计算距离工具类
- 网络分析系列之十三 Wireshark显示过滤器
- mtouch 3d gis,m3dgis,mtgis,mgis 多点触摸三维电子沙盘可视化交互系统教程第17课
- android 二级联动列表,仿eleme点餐页面
- Fiddler抓部分app时网络连接失败
- 【青龙面板】快手JS版脚本
- Docker、nvidia-container-toolkit安装与常用docker命令及docker镜像和容器的更新维护
- mac无法更新计算机的启动配置,MacOS 更新遇到的问题及重装系统
- YumRepo Error: All mirror URLs are not using ftp, http[s] or file解决办法
- 【多线程】c语言中的多线程
热门文章
- 【UVA - 10154 】Weights and Measures (贪心排序,dp,类似0-1背包,状态设定思维)
- ACM与Java -- 大整数类的常用函数一览表
- 【CodeForces - 570A】Elections(模拟,水题)
- 【HDU - 6290】 奢侈的旅行 (对题目预处理 + DIjkstra最短路)
- IMX6怎么移植最新Android,[IMX6Q][Android5.1]移植筆記 --- 無法掛載system文件系統
- matlab将模型解封装,模型保护
- MATLAB Simulink
- MathWorks 中国
- html 表格文字颜色 css,CSS 表格-JavaScript中文网-JavaScript教程资源分享门户
- linux缓存文件用户权限错误,Laravel运行缓存权限问题
- linux 计划任务格式,linux crontab 定时任务格式和使用方法2019-01-13
- java车次信息_从火车站车次公示栏来学Java读写锁