一、为什么需要面向切面编程?

面向对象编程(OOP)的好处是显而易见的,缺点也同样明显。当需要为多个不具有继承关系的对象添加一个公共的方法的时候,例如日志记录、性能监控等,如果采用面向对象编程的方法,需要在每个对象里面都添加相同的方法,这样就产生了较大的重复工作量和大量的重复代码,不利于维护。面向切面编程(AOP)是面向对象编程的补充,简单来说就是统一处理某一“切面”的问题的编程思想。如果使用AOP的方式进行日志的记录和处理,所有的日志代码都集中于一处,不需要再每个方法里面都去添加,极大减少了重复代码。

二、Spring AOP术语

通知(Advice)包含了需要用于多个应用对象的横切行为,完全听不懂,没关系,通俗一点说就是定义了“什么时候”和“做什么”。

连接点(Join Point)是程序执行过程中能够应用通知的所有点。

切点(Poincut)是定义了在“什么地方”进行切入,哪些连接点会得到通知。显然,切点一定是连接点。

切面(Aspect)是通知和切点的结合。通知和切点共同定义了切面的全部内容——是什么,何时,何地完成功能。

引入(Introduction)允许我们向现有的类中添加新方法或者属性。

织入(Weaving)是把切面应用到目标对象并创建新的代理对象的过程,分为编译期织入、类加载期织入和运行期织入。

三、Spring Boot AOP实战

3.1 引入依赖

Spring Boot使用AOP需要添加spring-boot-starter-aop依赖,如下:

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

不需要再添加aspectjweaver的依赖了,因为spring-boot-starter-aop包含了aspectjweaver,并且版本是较新的版本,如果在添加老版本(如1.5.4)启动会报错。

3.2 编写用于拦截的bean

直接定义一个controller,代码如下:

@RestController
public class AopController { @RequestMapping("/hello")
public String sayHello(){
System.out.println("hello");
return "hello";
}
}

3.3 定义切面

Spring采用@AspectJ注解对POJO进行标注,该注解表明该类不仅仅是一个POJO,还是一个切面。切面是切点和通知的结合,那么定义一个切面就需要编写切点和通知。在代码中,只需要添加@Aspect注解即可。

3.3.1 定义切点

切点是通过@Pointcut注解和切点表达式定义的。

@Pointcut注解可以在一个切面内定义可重用的切点。

由于Spring切面粒度最小是达到方法级别,而execution表达式可以用于明确指定方法返回类型,类名,方法名和参数名等与方法相关的部件,并且实际中,大部分需要使用AOP的业务场景也只需要达到方法级别即可,因而execution表达式的使用是最为广泛的。如图是execution表达式的语法:

execution表示在方法执行的时候触发。以“”开头,表明方法返回值类型为任意类型。然后是全限定的类名和方法名,“”可以表示任意类和任意方法。对于方法参数列表,可以使用“..”表示参数为任意类型。如果需要多个表达式,可以使用“&&”、“||”和“!”完成与、或、非的操作。

3.3.2 定义通知

通知有五种类型,分别是:

前置通知(@Before):在目标方法调用之前调用通知

后置通知(@After):在目标方法完成之后调用通知

环绕通知(@Around):在被通知的方法调用之前和调用之后执行自定义的方法

返回通知(@AfterReturning):在目标方法成功执行之后调用通知

异常通知(@AfterThrowing):在目标方法抛出异常之后调用通知

代码中定义了三种类型的通知,使用@Before注解标识前置通知,打印“beforeAdvice...”,使用@After注解标识后置通知,打印“AfterAdvice...”,使用@Around注解标识环绕通知,在方法执行前和执行之后分别打印“before”和“after”。这样一个切面就定义好了,代码如下:

@Aspect
@Component
public class AopAdvice { @Pointcut("execution (* com.shangguan.aop.controller.*.*(..))")
public void test() { } @Before("test()")
public void beforeAdvice() {
System.out.println("beforeAdvice...");
} @After("test()")
public void afterAdvice() {
System.out.println("afterAdvice...");
} @Around("test()")
public void aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
System.out.println("before");
try {
proceedingJoinPoint.proceed();
} catch (Throwable t) {
t.printStackTrace();
}
System.out.println("after");
} }

3.4 启动测试

完成之后的代码结构如图所示:

运行AopApplication,在浏览器访问http://localhost:8080/hello,不出意外,控制台输出如图所示:

Spring Boot使用AOP的正确姿势的更多相关文章

  1. spring boot 使用 AOP 的正确姿势 --- 心得

    1.前言 向spring boot转型,所有的配置基本上是用注解完成 ,以前使用spring MVC 需要写一大堆xml文件来配置. 基本上没什么变化,但是有些地方需要注意: 环绕通知不要使用异常捕获 ...

  2. spring boot 中AOP的使用

    一.AOP统一处理请求日志 也谈AOP 1.AOP是一种编程范式 2.与语言无关,是一种程序设计思想 面向切面(AOP)Aspect Oriented Programming 面向对象(OOP)Obj ...

  3. Spring Boot学习——AOP编程的简单实现

    首先应该明白一点,AOP是一种编程范式,是一种程序设计思想,与具体的计算机编程语言无关,所以不止是Java,像.Net等其他编程语言也有AOP的实现方式.AOP的思想理念就是将通用逻辑从业务逻辑中分离 ...

  4. spring boot使用AOP切面编程

    spring boot使用AOP 1.在pom文件中添加依赖: <!--spring boot aop切面--> <dependency> <groupId>org ...

  5. Spring Boot 使用 Aop 实现日志全局拦截

    前面的章节我们学习到 Spring Boot Log 日志使用教程 和 Spring Boot 异常处理与全局异常处理,本章我们结合 Aop 面向切面编程来实现全局拦截异常并记录日志. 在 Sprin ...

  6. spring boot+自定义 AOP 实现全局校验

    最近公司重构项目,重构为最热的微服务框架 spring boot, 重构的时候遇到几个可以统一处理的问题,也是项目中经常遇到,列如:统一校验参数,统一捕获异常... 仅凭代码 去控制参数的校验,有时候 ...

  7. Spring Boot 使用 AOP 实现页面自适应

    鉴于复杂页面自适应的难度,一般会做几套模板分别适应手机.平板.电脑等设备.使用 Spring Boot 开发单体应用时,一般会使用 Thymeleaf 模板,那么可以使用 AOP 技术来实现页面自适应 ...

  8. Spring Boot使用AOP在控制台打印请求、响应信息

    AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等. AOP简介 AOP全称Aspect Oriented Programming,面向切面,AOP主要实现的 ...

  9. Spring Boot系列——AOP配自定义注解的最佳实践

    AOP(Aspect Oriented Programming),即面向切面编程,是Spring框架的大杀器之一. 首先,我声明下,我不是来系统介绍什么是AOP,更不是照本宣科讲解什么是连接点.切面. ...

随机推荐

  1. JavaWeb网上图书商城完整项目--过滤器解决中文乱码

    我们知道,如果是POST请求,我们需要调用request.setCharacterEncoding(“utf-8”)方法来设计编码:如果是GET请求,我们需要自己手动来处理编码问题.如果我们使用了En ...

  2. mysql错误详解(1819):ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

    O(∩_∩)O哈哈~ 在学习 Mysql 的时候又遇到了新问题了 o(╥﹏╥)o 当我在准备为用户授权的时候: grant all privileges on *.* to 'root'@'%' id ...

  3. GCC编译和链接过程

    GCC(GNU Compiler Collection,GNU编译器套件),是由 GNU 开发的编程语言编译器.它是以GPL许可证所发行的自由软件,也是 GNU计划的关键部分.GCC原本作为GNU操作 ...

  4. Spring IoC 循环依赖的处理

    前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 本篇文章主要介绍 Spring IoC 是 ...

  5. maven跳过测试打包

    1.在执行run as时候加上参数: clean install compile -Dmaven.test.skip=true   2.在pom文件中添加如下: <plugins> < ...

  6. cv2.VideoCapture 图像旋转问题

    使用cv2.VideoCapture()时发现,分解后的图片均顺时针旋转90度, 为了重新转回来使用np.rot90(mat, 1)即逆时针将矩阵旋转90度. 大功告成!!!

  7. RS232/485通信方式 保存和加载时数据的处理

    RS232/485通信方式 数据以RS232/485方式通信时,以0xA5作为开始码,以0xAE作为结束码.在开始码和结束码之间的0xA5, 0xAA, 0xAE数据需要进行转码. PC端发送数据时将 ...

  8. JavaScript基础正则表达式的字面声明(012)

    不出所料,正则表达式也是JavaScript的一种对象.构造正则表达式也有两种,一种是使用JavaScript内置的 new RegExp() 构造函数,另一种是我们推荐的字面声明方式: // reg ...

  9. JS动画三剑客——setTimeout、setInterval、requestAnimationFrame

    一.前言 前端实现动画效果主要有以下几种方法:CSS3中的transition 和 animation ,Javascript 中可以通过定时器 setTimeout.setinterval,HTML ...

  10. Java基础Day07(Map Calender Date 包装类 System类 异常)

    1.Map Map是集合容器,存放的元素有键与值两部分组成,通过键可以找到所对应的值,键和值必须是引用数据类型,键是唯一的,不能重复,没有顺序. HashMap是Map的实现类. Map的添加,删除, ...