1. 项目概述
在Java开发领域,Spring框架的AOP(面向切面编程)功能一直是其核心特性之一。今天我们要探讨的是Spring AOP中一个关键概念——PointcutAdvisor的实现原理。这个看似简单的"Pointcut和Advice组合"背后,实际上隐藏着Spring框架设计者对于横切关注点处理的精妙思考。
作为一个在Java领域摸爬滚打多年的开发者,我见过太多对AOP理解停留在表面的案例。很多人知道@Aspect注解怎么用,但一旦需要自定义Advisor或者深入性能调优时就束手无策。本文将带你从零开始实现一个mini版的PointcutAdvisor,通过造轮子的方式真正理解Spring AOP的设计哲学。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心概念解析
2.1 AOP基础架构
AOP的核心价值在于将横切关注点(如日志、事务、权限等)与业务逻辑解耦。Spring AOP通过代理模式实现这一目标,而PointcutAdvisor正是连接切点定义和增强逻辑的桥梁。
在标准的Spring AOP中,完整的调用链是这样的:
code复制调用者 -> 代理对象 -> Advisor链 -> 目标方法
每个Advisor都包含两个关键部分:
- Pointcut:决定在哪些连接点(方法)上应用增强
- Advice:定义具体的增强逻辑(前置、后置、环绕等)
2.2 PointcutAdvisor接口设计
让我们先看看Spring中PointcutAdvisor的标准定义:
java复制public interface PointcutAdvisor extends Advisor {
Pointcut getPointcut();
Advice getAdvice();
}
这个接口看似简单,却体现了"单一职责"和"接口隔离"原则。它明确规定了:
- 一个Advisor必须能提供Pointcut
- 一个Advisor必须能提供Advice
- 不关心具体实现方式(可以是基于注解、表达式或编程式)
3. 实现细节剖析
3.1 基础实现类AbstractPointcutAdvisor
Spring提供了AbstractPointcutAdvisor作为基础实现:
java复制public abstract class AbstractPointcutAdvisor implements PointcutAdvisor, Serializable {
private Advice advice = EMPTY_ADVICE;
public void setAdvice(Advice advice) {
this.advice = advice;
}
@Override
public Advice getAdvice() {
return this.advice;
}
}
这个抽象类做了两件重要的事:
- 默认实现了Advice的存储和获取
- 留出Pointcut的获取方法作为抽象(强制子类实现)
提示:EMPTY_ADVICE是一个空实现,这种模式在框架设计中很常见,可以避免NPE问题。
3.2 典型实现AspectJExpressionPointcutAdvisor
Spring中最常用的实现是AspectJExpressionPointcutAdvisor:
java复制public class AspectJExpressionPointcutAdvisor extends AbstractPointcutAdvisor {
private final AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
public void setExpression(String expression) {
this.pointcut.setExpression(expression);
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
这个实现的关键点在于:
- 组合了AspectJExpressionPointcut(支持AspectJ切点表达式)
- 通过setExpression方法暴露配置入口
- 实现了getPointcut方法返回内部Pointcut实例
