当前位置: 首页 > news >正文

Spring Boot Aop初接触

AOP(面向切面编程),或多或少都听过一点。名字比较怪,切面,不容易理解,但其中真正含义,无非就是旁路控制,非侵入式编码之类。比如我想加个操作日志功能,利用AOP,无须每个操作都加一个记录功能,只需写一个,就惠泽全部。

这个是怎么做到的呢?也没有太玄妙的东西,原理类似于过滤器、拦截器,在底层和全局性的地方做了处理,各个业务功能都流经这些关卡。
在这里插入图片描述

一、过滤器、拦截器与AOP

据说,过滤器、拦截器、AOP三者功能类似,但各有优势,从过滤器 》拦截器 》切面,拦截规则越来越细致,执行顺序依次是过滤器、拦截器、切面。一般情况下数据被过滤的时机越早对服务的性能影响越小,因此我们在编写相对比较公用的代码时,优先考虑过滤器,然后是拦截器,最后是AOP。

AOP使用的主要是动态代理 , 过滤器使用的主要是函数回调;拦截器使用是反射机制 。一个请求过来,先进行过滤器处理,看程序是否受理该请求 。 过滤器放过后 , 程序中的拦截器进行处理 ,处理完后进入 被 AOP动态代理重新编译过的主要业务类进行处理 。

Filter:和框架无关,过滤器拦截的是URL,可以控制最初的http请求,但是更细一点的类和方法控制不了。

Interceptor:拦截器拦截的也是URL,拦截器有三个方法,相对于过滤器更加细致,有被拦截逻辑执行前、后等。

AOP:面向切面拦截的是类的元数据(包、类、方法名、参数等) 相对于拦截器更加细致,而且非常灵活,拦截器只能针对URL做拦截,而AOP针对具体的代码,能够实现更加复杂的业务逻辑。

二、Spring Boot中应用AOP

1、pom.xml

引入依赖包

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2、面向切面类

1)写一个方法用于测试

为方便测试,写一个控制器。再简单不过的控制器。

TestController.java

package com.chenqu.bullshit.modules.work.controller;@RestController
@RequestMapping("test1")
public class TestController {@ResponseBody@RequestMapping("/hello")public String sayHello(){System.out.println("hello");return "hello";}
}

2)面向切面的类

然后写一个面向切面的类。就像配置、过滤器、拦截器一样,写出来之后,系统(准确来说,应该是容器?)会自动解释它,于是面向切面开始生效。

TestAdvice.java

@Aspect
@Component
public class TestAdvice {//指示哪些方法将会受到影响。Pointcut,切入点@Pointcut("execution (* com.chenqu.bullshit.modules.work.controller.TestController.*(..))")public void test1() {}@Before("test1()")public void beforeAdvice() {System.out.println("beforeAdvice...");}@After("test1()")public void afterAdvice() {System.out.println("afterAdvice...");}@Around("test1()")public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {System.out.println("before");try {proceedingJoinPoint.proceed();} catch (Throwable t) {t.printStackTrace();}System.out.println("after");}
}

上述代码中,首先类使用了标注“@Aspect”,表明这是一个面向切面的类。

类中void test1()使用了标注“@Pointcut”。Pointcut者,切入点也。它里面的内容,指示了哪些方法将会受到影响。在这里,指向了我们用于测试的控制器。如果是想指向所有的控制器,可以这样写:

@Pointcut("execution (* com.chenqu.bullshit.modules.work.controller.*.*(..))")

在这里插入图片描述
至于其他的什么@Before、@After、@Arround,无非就是切入前执行、切入后执行、切入时执行,顾名思义。

运行代码,用浏览器访问

http://localhost:8090/test1/hello

控制台输出如下:
在这里插入图片描述

3、execution 与 annotation

execution与annotation都是Pointcut的2种常用执行方式,除此而外,还有什么within、this、target之类乱七八糟的,一大群,让人头大。常用的就是execution与annotation。execution如上例,就是指明会影响哪些方法;而annotation是注解的意思,指明会影响带哪些注解的方法,或者说,如果方法带上指定的注解,就会受到影响。

1)添加一个名为NeedTest的注解

NeedTest.java

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface NeedTest {String value() default "";
}

2)然后将上面例子中TestAdvice.java,Pointcut的执行方式由execution 改为 annotation,其余保持不变。

@Aspect
@Component
public class TestAdvice {@Pointcut("@annotation(com.chenqu.bullshit.modules.annotation.NeedTest)")public void test1() {}@Before("test1()")public void beforeAdvice() {System.out.println("beforeAdvice...");}@After("test1()")public void afterAdvice() {System.out.println("afterAdvice...");}@Around("test1()")public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {System.out.println("before");try {proceedingJoinPoint.proceed();} catch (Throwable t) {t.printStackTrace();}System.out.println("after");}}

3)修改用于测试的控制器TestController.java,方法带上@NeedTest注解

package com.chenqu.bullshit.modules.work.controller;@RestController
@RequestMapping("test1")
public class TestController {@NeedTest@ResponseBody@RequestMapping("/hello")public String sayHello(){System.out.println("hello");return "hello";}
}

运行结果跟上面一样,效果一致。

三、小结

从网上搜索出来的,有关spring boot aop的使用资料,绝大部分都很难懂。说了一大堆,根本不知道在说什么,也许作为手册供查阅是极好的。本文从我个人学习的角度出发,记录一下心得。

参考文章:
Spring Boot使用AOP的正确姿势

http://www.lryc.cn/news/44415.html

相关文章:

  • 【创作赢红包】LeetCode:232. 用栈实现队列
  • Mybatis+Mysql 实现向下递归查询
  • python@调用系统命令行@os.system@subprocess@标准输入输出@sys.stdin@sys.stdout@input@print
  • 手握数据智能密钥,诸葛智能打开数字化经营“三重门”
  • C语言可以实现各种滤波算法
  • 使用Netty,当然也要了解它的连接闲置处理
  • 2、K-Planes
  • 张文海教授课题组在国际高水平期刊《Cerebral Cortex》发表研究成果
  • ffmpeg4.1 源码学习之-转封装
  • ChatGPT写作文章-快速使用ChatGPT不用注册方式
  • Nginx配置ip白名单(服务权限控制)
  • Vue 核心(二)
  • 犯罪现场还原虚拟vr训练平台突破各种教学限制
  • LeetCode 617. 合并二叉树 | C++语言版
  • Python量化交易08——利用Tushare获取日K数据
  • 30张精美可视化大屏,无需代码直接套用,解决你95%的大屏需求!
  • TCP网络事件模型的封装1.0
  • NC271.二叉搜索树的后序遍历序列
  • 研究fastdds v2.8.0 1之 基础模块
  • ElasticSearch系列 - SpringBoot整合ES:精确值查询 term
  • 关于async/await、promise和setTimeout执行顺序
  • 2023-03-31:如何计算字符串中不同的非空回文子序列个数?
  • D. The Number of Imposters(二分图染色)
  • 图片太大怎么改小kb?简单的图片压缩方法分享
  • 【python-leecode刷题】动态规划类问题----以53. 最大子数组和为例
  • Idea常用快捷键设置
  • 【新2023Q2模拟题JAVA】华为OD机试 - 分苹果
  • 【博学谷学习记录】超强总结,用心分享丨人工智能 自然语言处理 BERT、GPT、ELMO对比学习简记
  • 【嵌入式Bluetooth应用开发笔记】第四篇:初探蓝牙HOST及应用开发(持续更新ing)
  • GORM 基础 -- CRUD 接口