【Programming】面向切面编程(AOP)

Posted by 西维蜀黍 on 2019-04-08, Last Modified on 2021-09-21

Aspect Oriented Programming (AOP)

背景

AOP(Aspect Oriented Programming),即面向切面编程,可以说是 **OOP(Object Oriented Programming,面向对象编程)** 的补充和完善。

OOP 引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。

不过,OOP 只允许开发者定义纵向的关系,而不能定义横向的关系,例如日志功能。因此,负责日志处理的代码不得不横向且重复地与业务逻辑(business logic)代码混合在一起。

而这些负责日志处理的代码,与附近的业务逻辑(business logic)代码毫无关系。这种散布在各处的与业务逻辑无关的代码被称为横切(cross cutting)

因此,在 OOP 设计中,它导致了大量代码的重复,而不利于各个模块的重用。

AOP(Aspect Oriented Programming)

AOP 技术恰恰相反,它利用一种称为” 横切” 的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为 **“Aspect”,即切面。所谓 “切面”**,简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

使用 **“横切” 技术,AOP 把软件系统分为两个部分:核心关注点横切关注点 **。

核心关注点,比如登陆,增加数据,删除数据都叫核心业务 横切关注点,比如性能统计,日志,事务管理等等

业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

AOP 目的

AOP 能够将那些本身与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

AOP 术语

在我们开始使用 AOP 工作之前,让我们熟悉一下 AOP 概念和术语。这些术语并不特定于 Spring,而是与 AOP 有关的。

描述
Joinpoint(连接点) 被拦截到的点,因为 Spring 只支持方法类型的连接点,所以在 Spring 中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
Pointcut(切入点) 这是一组一个或多个连接点,通知应该被执行。你可以使用表达式或模式指定切入点正如我们将在 AOP 的例子中看到的
Advice(通知) 这是实际行动之前或之后执行的方法。这是在程序执行期间通过 Spring AOP 框架实际被调用的代码
Aspect(切面) 一个模块具有一组提供横切需求的 APIs。例如,一个日志模块为了记录日志将被 AOP 方面调用。应用程序可以拥有任意数量的方面,这取决于需求
Weaving(织入) Weaving 把方面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象。这些可以在编译时,类加载时和运行时完成
Introduction(引入) 在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

通知的类型

Spring 方面可以使用下面提到的五种通知工作:

通知 描述
前置通知(Before advice) 在一个方法执行之前,执行通知。
最终通知(After (finally) advice) 在一个方法执行之后,不考虑其结果,执行的通知。
返回后通知(After returning advice) 在一个方法执行之后,只有在方法成功完成时,才能执行通知。
异常通知(After throwing advice) 在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。
环绕通知(Around Advice) 在建议方法调用之前和之后,执行通知。

Spring 对 AOP 的支持

Spring 中 AOP 代理由 Spring 的 **IoC 容器(Inversion of Control Container)** 负责生成、管理,其依赖关系也由 IoC 容器负责管理。因此,AOP 代理可以直接使用容器中的其它 bean 实例作为目标,这种关系可由 IoC 容器的依赖注入提供。

Spring 创建代理的规则为:

  1. 默认使用 Java 动态代理来创建 AOP 代理,这样就可以为任何接口实例创建代理了;
  2. 当需要代理的类不是代理接口的时候,Spring 会切换为使用 CGLIB 代理,也可强制使用 CGLIB;

AOP 编程其实是很简单的事情,纵观 AOP 编程,程序员只需要参与三个部分:

  1. 定义普通业务组件;
  2. 定义切入点,一个切入点可能横切多个业务组件;
  3. 定义增强处理,增强处理就是在 AOP 框架为普通业务组件织入的处理动作。

所以进行 AOP 编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP 框架将自动生成 AOP 代理,即:代理对象的方法 = 增强处理 + 被代理对象的方法。

主要功能

  • 日志记录
  • 性能统计
  • 安全控制
  • 事物处理
  • 异常处理

Reference