一、引言
在软件开发的世界中,代码的复杂性往往随着业务逻辑的扩展而增长。为了管理这种复杂性,传统的面向对象编程(OOP)提供了模块化的代码结构,但在处理跨越多个模块的通用功能时,OOP 的局限性显露无遗。于是,面向切面编程(AOP)应运而生。AOP 通过将关注点分离,将那些常见的非核心功能,如日志记录、安全检查、事务管理等,独立出来,从而简化了核心业务逻辑的开发和维护。
在这篇博客中,我们将深入探讨 AOP 的核心思想、应用场景以及如何利用它解锁更高效、更清晰的编程方式。通过这次 "AOP 革命",你将掌握解锁面向切面编程终极奥义的关键,进一步提升你的开发效率与代码质量。
二、AOP 概述
2.1、什么是 AOP
AOP 的全称叫做 Aspect Oriented Programming(面向切面编程),这里的切面可不是在数学中的那种切面,这里的切面就是指某⼀类特定问题,所以 AOP 也可以理解为面向特定方法编程。什么是面向特定方法编程呢?比如 "登录校验"、"返回值统一处理" 就是⼀类特定问题。登录校验拦截器,就是对 "登录校验" 这类问题的统⼀处理。所以,拦截器也是 AOP 的⼀种应用。AOP 是⼀种思想,拦截器是 AOP 思想的⼀种实现。Spring 框架实现了这种思想,提供了拦截器技术的相关接口。同样的,统⼀数据返回格式和统⼀异常处理,也是 AOP 思想的⼀种实现。
简单来说:AOP 是⼀种思想,是对某⼀类事情的集中处理。
三、使用 AOP
3.1、引入依赖
在 "pom.xml" 文件中添加配置
3.2、编写 AOP 程序
在正式编写 AOP 的程序之前,我们首先要知道如何告诉 Spring 我们是在编写一个 AOP 的东西呢?这就得用到我们的 Aspect
注解,声明我们这个类是切面类了,程序如下:
然后我们 Controller 的代码和正常的一样:
按照道理来说,如果这里没有切面类,那我们的程序在控制台中,什么都不会打印,然后网页正常显示 "doAround Run...",但是加了切面类,控制台变成了这样:
所以,这个切面类更贴切的一种理解是这样的:本来通过 URL 是直接和我们所对应的方法连接的,但是这个切面类给这种连接切断了,从中间插了一脚,然后通过这个切面类访问的目标类,有点像代理模式,但是不仅限于代理模式,添加了一些其他的东西,它允许开发者将影响多个应用程序部分的问题(如日志记录、事务管理等)集中处理,而不是分散在多处代码中。按照我的个人理解是 AOP 的实现原理是基于代理模式的,但不限于此。
3.3、Spring AOP 核心概念
a)切点
切点,也称之为 "切入点",切点的作用就是提供一组规则(使用 AspectJ pointcut expression language 来描述),告诉程序对哪些方法来进行功能增强。也就是我们使用的 @Around
注解括号后面的 execution(* com.zmbdp.aopdemo.blogtest.*.*(..))
就是切点表达式。
b)连接点
连接点就是原本要执行的方法,比如说上面写的切点代码,因为后面是 * ,blogtest
这个包的类的所有方法就是连接点。
c)通知
通知就是具体要做的工作,指哪些重复的逻辑,也就是共性功能(最终体现为一个方法)比如上述程序中打印的日志,就是通知。
d)切面
切面 = 切点 + 通知
图解如下:
3.4、通知类型
上⾯我们讲了什么是通知, 接下来学习通知的类型.
@Around
就是其中⼀种通知类型,表示环绕通知。Spring 中 AOP 的通知类型有以下几种:
@Around
:环绕通知,此注解标注的通知方法在目标方法前、后都被执行@Before
:前置通知,此注解标注的通知方法在目标方法前被执行@After
:后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行@AfterReturning
:返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行@AfterThrowing
:异常后通知,此注解标注的通知方法发生异常后执行
这些方法的执行顺序呢是 @Around前
> @Before
> @AfterReturning
> @After
> @Around后
,如果说有异常,那么 @AfterReturning
和 @Around后
就不会执行,@AfterReturning
就会被替换成 @AfterThrowing
。
3.5、切面优先级
假设我们这时候定义了多个切面,比如:
运行结果如下:
由此我们能判断这个切面执行的顺序是根据切面类名字的 ASCll 值来判定的,并且限制性的切面类后结束。那我们程序猿肯定不会计算他的 ASCll 值啊,所以我们可以使用 @Order
这个注解来自定义优先级,如下:
执行结果如下:
3.6、自定义 AOP
execution 表达式更适用有规则的,如果说我们要匹配多个无规则的方法呢?
这时候 execution 就只能在类上使用了,当我们自定义一个注解的时候,我们就可以设置它是能在方法上用的注解了,如下:
然后我们的要使用的方法加上 @MyAspect
这个注解就行了,运行结果如下:
四、总结
在本文中,我们深入探讨了面向切面编程(AOP)的核心思想、应用场景及其在 Spring 框架中的具体实现。AOP 通过分离关注点,将诸如日志记录、安全检查、事务管理等非核心业务逻辑从核心代码中抽离出来,从而简化了代码结构,提高了代码的可维护性和开发效率。
我们首先从 AOP 的定义入手,明确了 AOP 是一种编程思想,它关注于对某类特定问题的集中处理。随后,我们详细介绍了如何在Spring框架中引入 AOP 依赖、编写 AOP 程序,并通过实际代码示例展示了如何使用 @Aspect
注解来定义切面,以及如何通过切点表达式来指定哪些方法需要被增强。
在深入 AOP 的核心概念时,我们解释了切点、连接点、通知和切面等关键术语,并通过图解的方式帮助读者更好地理解它们之间的关系。此外,我们还详细讲解了不同类型的通知(如环绕通知、前置通知、后置通知、返回后通知和异常后通知),并讨论了这些通知的执行顺序。
对于切面优先级的问题,我们介绍了如何通过 @Order
注解来自定义切面的执行顺序,从而解决了多个切面同时存在时可能出现的执行顺序问题。
最后,我们探讨了如何自定义 AOP,通过定义一个自定义注解,并基于该注解来指定哪些方法需要被增强,从而实现了对无规则方法的匹配和处理。
五、结语
通过本文的学习,相信读者已经对 AOP 有了更深入的理解,并掌握了在 Spring 框架中使用 AOP 的基本方法。AOP 作为一种强大的编程范式,不仅能够帮助我们更好地管理代码的复杂性,还能提高代码的重用性和可维护性。在未来的软件开发过程中,我们可以更加灵活地运用 AOP 思想来优化我们的代码结构,提升开发效率。
希望本文能够成为你掌握 AOP 的得力助手,也期待你在未来的软件开发中能够灵活运用 AOP,创造出更加高效、清晰的代码。让我们一起在 AOP 的 "革命" 中,解锁更高效、更清晰的编程方式吧!下篇博客见。