AOP基本概念
AOP(Aspect-Oriented Programming),即“面向切面编程”。
AOP是什么
简单通俗地来说:AOP(面向切面编程)是一种:把“与核心业务无关、但到处都需要的逻辑”从业务代码中分离出来,并在合适的时机自动执行的编程思想。
——AOP是一种编程思想。
AOP一般的应用场景:日志、权限校验、事务、监控、缓存、异常处理……
它们的共同特征:
- 横跨大量业务逻辑
- 实现方式高度重复
- 和业务目标本身无关
这类问题叫:横切关注点(Cross-Cutting Concerns),而AOP 的目的只有一个:让这些“横着切进来的逻辑”不再污染业务代码。
AOP的重要基本概念
切面(Aspect)
一组横切逻辑的集合
切面的本质就是:规则的集合。它包含“在哪个地方 + 什么时候 + 要做什么”,例如:在所有网络请求接口 → 调用前 → 校验权限。
切面是对“要做什么事情”的抽象(集合)。
连接点(Join Point)
程序执行过程中,天然存在的、可以被拦截的位置
常见连接点(跨语言):
- 函数 / 方法调用
- 函数返回
- 抛异常
- 对象创建
- 属性访问(部分语言支持)
需要强调:“连接点”的概念虽然可能由AOP提出,但是连接点的存在和AOP没有任何关系,因为连接点是程序执行时天然存在的。
连接点(Join Point)是一个在执行AOP功能中“通知(Advice)”的基础依据。正是“连接点”的天然存在,让AOP可以“在什么地方、什么时候”执行通知。
切点(Pointcut)
对连接点( Join Point) 的筛选规则
切点(Pointcut)是匹配(筛选)连接点(Join Point)的判断规则(谓词),一般表现为要执行通知(Advice)的目标方法/函数。
如:所有 public 方法、所有 controller 层函数、标记了某个注解 / 装饰器的函数。
切点(Pointcut)明确地告诉AOP“在什么地方”执行通知。
通知(Advice)
在连接点上执行的具体逻辑和操作
常见类型(逻辑意义):
- Before:之前
- After:之后
- AfterThrowing:出错时
- Around:包住整个执行过程
通知(Advice)有两个作用:1.“什么时候做”;2.“做什么”。
如上所述,Before、After、AfterThrowing、Around指明了在连接点执行前、执行后、执行出错(异常)时、整个执行过程(执行前、执行中、执行后)执行具体的操作。
织入(Weaving)
把切面(Aspect)逻辑真正整合进程序执行流程的过程
它不是“定义”,而是真正发生时的动作,即如何在程序运行时真正地执行切面中的代码,将切面“织入”到目标切点的位置。
织入可以发生在:
- 编译期
- 加载期
- 运行期
织入(Weaving)由具体的AOP实现框架(Framework)(如Java的AsceptJ)采用具体语言能力(如Java的动态代理 / CGLIB)完成。
AOP的通用实现原理(跨语言视角)
第一:定义“可拦截点”(连接点)
任何语言,只要满足下面之一,就具备 AOP 的可能性:
- 可以拦截函数调用
- 可以改写调用流程
- 可以包裹原始逻辑
抽象表示:
原始执行流程:
call(target)
第二:定义“增强逻辑”(通知)
把横切逻辑抽象为函数:
before()
after()
onError()
这些逻辑 不关心业务细节。
第三:建立“匹配规则”(切点)
需要一个规则系统:
if (this execution matches rule) {
apply advice
}
这就是切点(Pointcut)的本质:一个“是否增强(通知)”的判定器。
第四(核心):改变执行流程
这是 AOP 的技术核心。
把原执行:
result = target()
变成:
before()
try {
result = target()
after()
} catch (e) {
onError(e)
}
或者(Around):
result = advice(() -> target())
所有 AOP,最终都会退化成“函数包函数”。
第五:选择织入时机
这是实现差异,而不是思想差异:
-
编译期
-
修改中间代码 / 字节码 / AST
-
代表:AspectJ、某些编译器插件
-
-
加载期
- 模块加载时注入
- 代表:字节码增强、ClassLoader Hook
-
运行期(最通用)
- 代理对象
- 装饰器
- 高阶函数
具体编程语言举例:
| 语言 | 技术 |
|---|---|
| Java | 动态代理 / CGLIB |
| Python | 装饰器 |
| JS | 函数包装 / Proxy |
| Go | middleware |
| C# | Castle DynamicProxy |
一个“语言无关”的 AOP 伪代码
function weave(target, advice):
return function(...args):
advice.before()
try:
result = target(...args)
advice.after()
return result
catch e:
advice.onError(e)
throw e
AOP本质总结
- AOP 不是某种语法,AOP 是一种“组织代码的方式”。
- AOP 的核心不是“切面”,核心是:控制执行流程。
- AOP 的终极抽象:AOP = 可拦截执行点(连接点) + 可插拔行为(通知) + 自动织入机制(织入)。