Spring学习笔记之AOP

Spring学习笔记(一)面向切面的Spring

  • 面向切面编程的基本原理
  • 通过POJO创建的切面
  • 使用AspectJ注解
  • 为AspectJ切面注入依赖

初识AOP

我们学习面向切面编程的第一步是了解什么是面向切面编程,这里想用一个日常生活中的例子来描述切面的概念。


夏天到了,休息的时候小伙伴们都喜欢待在家里吹空调让自己舒服一些,不过一旦我们使用过空调,它就会耗电,让电表转的飞快。每个月都会有人来查看电表,这样电力公司就知道应该收取多少费用了。监控电量是一个很重要的事情,但并不是我们重点关注的问题。我们实际上所关注的可能是哪家公司又出了新的手机,周末去看什么电影,或者抽时间看看自己感兴趣的书等等。从我们生活的角度,监控家里的用电量是一件十分被动的事情。


软件系统中的一些功能就像我们家里的电表一样。这些功能需要用到应用程序的多个地方,但是我们又不想在每个点都明确的调用它。比如说日志,安全和事务管理等。在软件开发中,散布于应用中多处的功能被称为横切关注点(cross-cutting concern)。这些横切关注点从概念上是与应用的业务逻辑相分离的。把这些横切关注点与应用逻辑相分离正式面向切面编程(AOP)所要解决的问题。


什么是面向切面编程

这是一个简单的应用图,图中切面实现了横切关注点(跨多个应用对象的逻辑)的模块化
Spring学习笔记之AOP
它是一个被划分为模块的典型应用。每个模块的核心功能都是为特定业务领域提供服务,但是这些模块都需要类似的辅助功能,例如安全和事务管理。
如果要重用通用功能的话,最常见的面向对象技术是继承(inheritance)或委托(delegation)。但是整个应用中都使用相同的基类,继承往往会导致一个脆弱的对象体质;而使用委托可能需要对委托对象进行复杂的调用。


切面提供了取代继承和委托的另一种可选方案,而且在很多场景下更清晰简洁。在使用面向切面编程时,我们仍然在一个地方定义通用功能,但是可以通过声明的方式定义这个功能要以何种方式在何处应用,而无需修改受影响的类。横切关注点可以被模块化为特殊的类,这些类被称为切面(aspect)。
这样做有两个好处:

  1. 每个关注点都集中于一个地方,而不是分散到多处代码中
  2. 服务模块更简洁,因为它们只包含主要关注点的代码,而次要关注点的代码被转移到了切面中

定义AOP

首先我们来学习一下AOP中的常用术语。通知(advice)、切点(pointcut)和连接点(joinpoint)。下图中展示了这些概念是如何关联在一起的。
Spring学习笔记之AOP


通知(advice):在AOP术语中切面的工作被称作通知。通知定义了切面是什么以及何时使用。除了描述切面要完成的工作,通知还解决了何时执行这个工作的问题。Spring切面可以应用5中类型的通知。

  • 前置通知(before):在目标方法被调用之前调用通知功能;
  • 后置通知(after):在目标方法完成之后调用通知功能,此时不会关心方法的输出是什么;
  • 返回通知(after-returning):在目标方法成功执行之后调用通知;
  • 异常通知(after-throwing):在目标方法抛出异常后调用通知;
  • 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。

切点(pointcut):如果说advice定义了切面的“什么”和“何时”的话,那么pointcut就定义了“何处”。切点的定义会匹配通知所要织入的一个或多个连接点。我们通常使用明确的类和方法名称,或是利用正则表达式定义所匹配的类和方法名称来制定这些切点。


连接点(joinpoint):连接点是在应用执行过程中能够被切面插入的点。这个点可以是调用方法时、抛出异常时、甚至修改一个字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。