中国建设银行个人网站注册,郑州网站开发与建设,四川省建设厅职改办网站,个人网站变现AOP#xff08;面向切面编程#xff09;#xff0c;或多或少都听过一点。名字比较怪#xff0c;切面#xff0c;不容易理解#xff0c;但其中真正含义#xff0c;无非就是旁路控制#xff0c;非侵入式编码之类。比如我想加个操作日志功能#xff0c;利用AOP#xff0…AOP面向切面编程或多或少都听过一点。名字比较怪切面不容易理解但其中真正含义无非就是旁路控制非侵入式编码之类。比如我想加个操作日志功能利用AOP无须每个操作都加一个记录功能只需写一个就惠泽全部。
这个是怎么做到的呢也没有太玄妙的东西原理类似于过滤器、拦截器在底层和全局性的地方做了处理各个业务功能都流经这些关卡。
一、过滤器、拦截器与AOP
据说过滤器、拦截器、AOP三者功能类似但各有优势从过滤器 》拦截器 》切面拦截规则越来越细致执行顺序依次是过滤器、拦截器、切面。一般情况下数据被过滤的时机越早对服务的性能影响越小因此我们在编写相对比较公用的代码时优先考虑过滤器然后是拦截器最后是AOP。
AOP使用的主要是动态代理 过滤器使用的主要是函数回调拦截器使用是反射机制 。一个请求过来先进行过滤器处理看程序是否受理该请求 。 过滤器放过后 程序中的拦截器进行处理 处理完后进入 被 AOP动态代理重新编译过的主要业务类进行处理 。
Filter和框架无关过滤器拦截的是URL可以控制最初的http请求但是更细一点的类和方法控制不了。
Interceptor拦截器拦截的也是URL拦截器有三个方法相对于过滤器更加细致有被拦截逻辑执行前、后等。
AOP面向切面拦截的是类的元数据包、类、方法名、参数等 相对于拦截器更加细致而且非常灵活拦截器只能针对URL做拦截而AOP针对具体的代码能够实现更加复杂的业务逻辑。
二、Spring Boot中应用AOP
1、pom.xml
引入依赖包
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId
/dependency2、面向切面类
1写一个方法用于测试
为方便测试写一个控制器。再简单不过的控制器。
TestController.java
package com.chenqu.bullshit.modules.work.controller;RestController
RequestMapping(test1)
public class TestController {ResponseBodyRequestMapping(/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.javaPointcut的执行方式由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 {NeedTestResponseBodyRequestMapping(/hello)public String sayHello(){System.out.println(hello);return hello;}
}运行结果跟上面一样效果一致。
三、小结
从网上搜索出来的有关spring boot aop的使用资料绝大部分都很难懂。说了一大堆根本不知道在说什么也许作为手册供查阅是极好的。本文从我个人学习的角度出发记录一下心得。
参考文章 Spring Boot使用AOP的正确姿势