AOP 核心原理 - JDK 动态代理 vs CGLIB 字节码增强
概述
AOP(Aspect-Oriented Programming,面向切面编程)是 Spring 框架的核心模块之一,它通过预编译方式和运行期动态代理来实现程序的横切关注点(如日志、事务、安全等)的模块化。
Spring AOP 的底层实现依赖于两种代理机制:JDK 动态代理和 CGLIB 字节码增强。理解这两者的原理与差异,是掌握 Spring AOP 的关键。
本文基于 Spring Framework 5.3.x 源码,从接口设计、代理创建流程、字节码生成机制等维度深度剖析 AOP 核心原理。
1. AOP 基本概念
在深入代理机制之前,先明确 AOP 的核心术语:
| 术语 | 英文 | 说明 |
|---|---|---|
| 切面 | Aspect | 横切关注点的模块化,如日志切面、事务切面。Spring 中通过 @Aspect 注解或 XML <aop:aspect> 声明 |
| 连接点 | Join Point | 程序执行过程中的某个特定点,如方法调用、异常抛出。Spring AOP 仅支持方法执行连接点 |
| 通知 | Advice | 在切面的某个连接点上执行的动作,包括 @Before、@After、@Around、@AfterReturning、@AfterThrowing 五种类型 |
| 切点 | Pointcut | 匹配连接点的断言,通过表达式(如 execution(* com.example..*.*(..)))定义哪些方法需要增强 |
| 引入 | Introduction | 为现有类添加新的方法或属性,Spring 中通过 @DeclareParents 实现 |
| 织入 | Weaving | 将切面应用到目标对象并创建代理对象的过程。Spring AOP 采用运行期织入,即通过代理对象在运行时增强 |
这六个概念的关系可以用以下公式概括:
AOP = Pointcut(在哪里切) + Advice(切什么逻辑) = Advisor(切面配置)2. JDK 动态代理原理
2.1 核心机制
JDK 动态代理是 Java 原生支持的代理机制,位于 java.lang.reflect 包下。其核心思想是:运行时动态生成一个实现了目标对象所有接口的代理类,通过 InvocationHandler 拦截所有方法调用。
核心类:
| 类/接口 | 作用 |
|---|---|
java.lang.reflect.Proxy | 静态工厂方法 newProxyInstance() 用于创建代理实例 |
java.lang.reflect.InvocationHandler | 代理实例的调用处理器接口,所有方法调用都会转发到其 invoke() 方法 |
java.lang.ClassLoader | 用于加载动态生成的代理类字节码 |
2.2 源码示例
// 目标接口
public interface UserService {
void createUser(String name);
String getUser(Long id);
}
// 目标实现类
public class UserServiceImpl implements UserService {
@Override
public void createUser(String name) {
System.out.println("创建用户: " + name);
}
@Override
public String getUser(Long id) {
return "用户: " + id;
}
}
// InvocationHandler 实现
public class LogInvocationHandler implements InvocationHandler {
private final Object target;
public LogInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("[JDK代理] 前置拦截 - 调用方法: " + method.getName());
Object result = method.invoke(target, args);
System.out.println("[JDK代理] 后置拦截 - 方法返回: " + result);
return result;
}
}
// 使用示例
public class JdkProxyDemo {
public static void main(String[] args) {
// 保存生成的代理类字节码到文件(需在启动时设置)
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
// JDK 8+ 使用:
// System.setProperty("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");
UserService target = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new LogInvocationHandler(target)
);
proxy.createUser("张三");
String result = proxy.getUser(1L);
System.out.println("结果: " + result);
}
}2.3 Proxy.newProxyInstance 源码分析
// java.lang.reflect.Proxy (JDK 源码)
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h) {
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
// 安全检查
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
// 核心步骤: 查找或生成代理类的 Class 对象
Class<?> cl = getProxyClass0(loader, intfs);
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
// 通过反射获取代理类的构造函数(参数为 InvocationHandler)
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
// 创建代理实例
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException | InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable te = e.getCause();
throw new InternalError(te.toString(), te);
}
}核心流程:
getProxyClass0(loader, intfs)— 从缓存中查找或通过ProxyClassFactory生成代理类的Class对象- 反射获取构造器 — 代理类的构造器接受一个
InvocationHandler参数 cons.newInstance(h)— 通过构造器创建代理实例
2.4 代理类字节码生成
ProxyClassFactory 内部通过 ProxyGenerator.generateProxyClass() 方法动态生成代理类的字节码:
// Proxy.ProxyClassFactory (JDK 内部类)
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>> {
private static final String proxyClassNamePrefix = "$Proxy";
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
// ... 省略接口验证逻辑 ...
// 生成代理类名称,格式: com.sun.proxy.$Proxy0
String proxyName = proxyPkg + "." + proxyClassNamePrefix + num;
// 核心: 调用 ProxyGenerator 生成字节码
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
// 通过 native 方法加载字节码
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
}
}生成的代理类(以 $Proxy0 为例)具有以下特征:
// 反编译 com.sun.proxy.$Proxy0
public final class $Proxy0 extends Proxy implements UserService {
// 每个接口方法的 Method 对象
private static Method m1; // equals
private static Method m2; // toString
private static Method m3; // createUser
private static Method m4; // getUser
private static Method m5; // hashCode
public $Proxy0(InvocationHandler h) {
super(h);
}
@Override
public final void createUser(String name) {
try {
// 所有调用都转发到 InvocationHandler.invoke()
super.h.invoke(this, m3, new Object[]{name});
return;
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
@Override
public final String getUser(Long id) {
try {
return (String) super.h.invoke(this, m4, new Object[]{id});
} catch (RuntimeException | Error e) {
throw e;
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
// equals, hashCode, toString 同样转发
}关键要点:
- 代理类继承
Proxy,实现目标接口(Java 单继承限制,因此只能代理接口) - 所有方法调用均转发到
InvocationHandler.invoke(),因此每个方法调用都会经过拦截 - 代理类用
final修饰,不可再被继承
3. CGLIB 字节码增强原理
3.1 核心机制
CGLIB(Code Generation Library)是一个高性能的字节码生成库,它通过动态生成目标类的子类来实现代理。CGLIB 使用 ASM 字节码框架来操作字节码,运行时生成新的类。
核心类:
| 类/接口 | 作用 |
|---|---|
net.sf.cglib.proxy.Enhancer | 核心增强类,用于创建代理对象 |
net.sf.cglib.proxy.MethodInterceptor | 方法拦截器接口,类似于 JDK 的 InvocationHandler |
net.sf.cglib.proxy.MethodProxy | 代理方法对象,提供比反射更高效的方法调用(FastClass 机制) |
net.sf.cglib.core.DefaultGeneratorStrategy | 字节码生成策略 |
3.2 源码示例
// 目标类(无需实现接口)
public class UserService {
public void createUser(String name) {
System.out.println("创建用户: " + name);
}
public String getUser(Long id) {
return "用户: " + id;
}
}
// MethodInterceptor 实现
public class LogMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("[CGLIB代理] 前置拦截 - 调用方法: " + method.getName());
// 注意: 这里使用 proxy.invokeSuper() 而非 method.invoke()
Object result = proxy.invokeSuper(obj, args);
System.out.println("[CGLIB代理] 后置拦截 - 方法返回: " + result);
return result;
}
}
// 使用示例
public class CglibProxyDemo {
public static void main(String[] args) {
// 保存生成的代理类字节码
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,
"target/cglib-classes");
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallback(new LogMethodInterceptor());
UserService proxy = (UserService) enhancer.create();
proxy.createUser("李四");
String result = proxy.getUser(2L);
System.out.println("结果: " + result);
}
}3.3 Enhancer.create 源码分析
// net.sf.cglib.proxy.Enhancer
public Object create() {
classOnly = false;
argumentTypes = null;
return createHelper();
}
private Object createHelper() {
// 前置验证
preValidate();
// 核心: 生成代理类的 Class 对象
Object key = KEY_FACTORY.newInstance(
superclass != null ? superclass.getName() : null,
interfaces,
filterType,
callbackTypes,
useFactory,
interceptDuring,
serialVersionUID);
this.currentKey = key;
// 通过 AbstractClassGenerator 生成或加载代理类
Object result = super.create(key);
return result;
}Enhancer 继承 AbstractClassGenerator,super.create(key) 最终会调用 generateClass() 方法,使用 ASM 生成子类的字节码。
3.4 生成的代理类结构
CGLIB 生成的代理类(以 UserService$$EnhancerByCGLIB$$xxxx 为例)具有以下特征:
// 反编译生成的代理类
public class UserService$$EnhancerByCGLIB$$abcdef extends UserService
implements Factory {
// MethodProxy 对象(每个方法对应一个)
private MethodProxy CGLIB$createUser$0$Method;
private MethodProxy CGLIB$getUser$1$Method;
// 目标方法的 Method 对象
private Method CGLIB$createUser$0$Method_fallback;
private Method CGLIB$getUser$1$Method_fallback;
// 回调数组(MethodInterceptor 存储在数组中)
private MethodInterceptor CGLIB$CALLBACK_0;
// 静态初始化块:初始化所有 MethodProxy
static {
CGLIB$STATICHOOK1();
}
// 重写父类方法
public final void createUser(String name) {
MethodInterceptor interceptor = CGLIB$CALLBACK_0;
if (interceptor != null) {
// 通过拦截器调用
interceptor.intercept(this,
CGLIB$createUser$0$Method,
new Object[]{name},
CGLIB$createUser$0$MethodProxy);
return;
}
// 无拦截器时调用父类方法
super.createUser(name);
}
public final String getUser(Long id) {
MethodInterceptor interceptor = CGLIB$CALLBACK_0;
if (interceptor != null) {
return (String) interceptor.intercept(this,
CGLIB$getUser$1$Method,
new Object[]{id},
CGLIB$getUser$1$MethodProxy);
}
return super.getUser(id);
}
}关键要点:
- 代理类继承目标类,因此 CGLIB 可以代理没有接口的类
- 每个被代理的方法都生成对应的
MethodProxy对象 - 方法内部先检查
Callback是否存在,存在则调用拦截器,否则直接调用父类方法 - 所有非抽象方法默认被
final修饰以防止子类覆盖(但 CGLIB 生成的类本身是用于被子类化的,这里 final 是指 CGLIB 自己的增强方法标记,实际生成的子类方法覆写了父类方法)
3.5 FastClass 机制
CGLIB 的 MethodProxy 之所以比 JDK 的 Method.invoke() 更快,关键在于其底层的 FastClass 机制。
// net.sf.cglib.proxy.MethodProxy
public class MethodProxy {
private String name;
private String desc;
private int sIndex; // 在 FastClass 中的索引(父类方法)
private int iIndex; // 在 FastClass 中的索引(子类方法)
private FastClass fastClass; // 目标类的 FastClass
private FastClass creator; // 代理类的 FastClass
// invokeSuper — 直接在父类上调用目标方法
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
// 通过 FastClass 索引直接调用,避免反射
fastClass.invoke(sIndex, obj, args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
// invoke — 在代理类上调用增强后的方法
public Object invoke(Object obj, Object[] args) throws Throwable {
try {
creator.invoke(iIndex, obj, args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
}FastClass 工作原理:
CGLIB 会为目标类和代理类各生成一个 FastClass 辅助类。FastClass 通过索引映射的方式,将方法调用从反射调用转为直接下标索引 + switch 语句调用:
// 为目标类 UserService 生成的 FastClass
public class UserService$$FastClassByCGLIB$$xxxx extends FastClass {
// 通过索引获取方法的 index
public int getIndex(String name, Class[] parameterTypes) {
switch (name) {
case "createUser":
return 0; // createUser 对应索引 0
case "getUser":
return 1; // getUser 对应索引 1
case "equals":
return 2;
case "hashCode":
return 3;
case "toString":
return 4;
}
return -1;
}
// invoke 方法通过 switch 直接调用,无需反射
public Object invoke(int index, Object obj, Object[] args) {
UserService target = (UserService) obj;
switch (index) {
case 0:
target.createUser((String) args[0]);
return null;
case 1:
return target.getUser((Long) args[0]);
case 2:
return target.equals(args[0]);
case 3:
return target.hashCode();
case 4:
return target.toString();
}
throw new IllegalArgumentException("Unknown index: " + index);
}
}性能对比:
反射调用: Method.invoke() → 安全检查 → native 调用 → 方法执行
FastClass: invoke(index) → switch 定位 → 强制类型转换 → 方法执行FastClass 省去了反射调用中的安全检查、包装类型转换等开销,性能提升约 2-5 倍。
4. JDK 动态代理 vs CGLIB 详细对比
4.1 核心差异对比表
| 维度 | JDK 动态代理 | CGLIB 动态代理 |
|---|---|---|
| 原理 | 运行时生成实现目标接口的代理类 | 运行时生成目标类的子类作为代理 |
| 依赖 | Java 原生支持,无需额外依赖 | 需要引入 cglib(Spring 已内置) |
| 目标要求 | 目标对象必须实现至少一个接口 | 目标对象无需实现接口 |
| 生成方式 | ProxyGenerator.generateProxyClass() | ASM 字节码操作 |
| 调用方式 | InvocationHandler.invoke()(反射) | MethodInterceptor.intercept() + MethodProxy(FastClass) |
| 调用性能 | 相对较慢(反射调用 + 装箱拆箱) | 较快(FastClass 索引调用) |
| 代理类特征 | 继承 Proxy,实现目标接口 | 继承目标类,实现 Factory 接口 |
| 能否代理 final 方法 | 不能(接口方法不能是 final) | 不能(不能覆写 final 方法) |
| 能否代理 static 方法 | 不能 | 不能 |
| 能否代理 private 方法 | 不能(接口方法默认 public) | 不能(子类不可见) |
| 对象创建速度 | 较快 | 较慢(需生成子类和 FastClass) |
4.2 Spring 中的选择策略
Spring 在 DefaultAopProxyFactory 中决定使用哪种代理:
// org.springframework.aop.framework.DefaultAopProxyFactory
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 判断条件 (Spring 5.x)
if (config.isOptimize() || config.isProxyTargetClass()
|| hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("...");
}
// 如果目标类是接口或已经是代理类,使用 JDK 动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 否则使用 CGLIB
return new ObjenesisCglibAopProxy(config);
} else {
// 默认:如果目标提供了接口且接口数量 > 0,使用 JDK 代理
return new JdkDynamicAopProxy(config);
}
}
}选择逻辑总结:
是否设置了 proxyTargetClass = true?
├── 是 → 判断目标类是否为接口或已有代理
│ ├── 是接口 → JDK 动态代理
│ └── 否 → CGLIB 代理
└── 否 → 判断目标是否实现了自定义接口(非 Spring 内部接口)
├── 是 → JDK 动态代理
└── 否(无接口或仅有 Spring 内部接口)→ CGLIB 代理4.3 各自的限制
JDK 动态代理的限制:
- 必须实现接口:如果目标类没有实现任何接口,无法使用 JDK 动态代理
- 调用性能较低:使用
Method.invoke()反射调用,且有装箱/拆箱开销 - 仅支持 public 方法:接口方法默认为
public,因此无法拦截protected/package-private/private方法
CGLIB 的限制:
- 不能代理 final 方法:子类无法覆写父类的
final方法 - 不能代理 final 类:无法继承
final类 - 不能代理 static 方法:方法重写只适用于实例方法
- 构造器调用两次:CGLIB 代理对象创建时会调用两次构造器(一次是生成代理类实例,一次是调用父类构造器)
this调用失效:目标类内部方法之间的this.method()调用不会经过代理,即 Spring AOP 默认不支持内部方法自调用的拦截
4.4 性能基准对比
| 场景 | JDK 动态代理 | CGLIB |
|---|---|---|
| 代理创建时间(首次) | 约 0.1ms | 约 1-5ms(需生成字节码) |
| 方法调用(1000万次) | 约 800ms | 约 300ms |
| 内存占用 | 较少 | 较多(额外 FastClass) |
| 预热后性能 | 稳定 | 更优 |
注意:在 Spring Boot 2.x / Spring 5.x 中,CGLIB 已成为默认的代理方式(
spring.aop.proxy-target-class=true)。
5. ProxyFactory 创建代理的流程
5.1 Spring AOP 代理工厂体系
Spring AOP 提供了一套完整的代理创建工厂体系:
AopProxy (接口)
├── JdkDynamicAopProxy — JDK 动态代理实现
└── CglibAopProxy — CGLIB 代理实现
AopProxyFactory (接口)
└── DefaultAopProxyFactory — 默认实现,决定使用哪种 AopProxy
ProxyCreatorSupport (基类)
└── ProxyFactory — 最常用的编程式 AOP 代理工厂5.2 编程式使用示例
// 1. 创建 ProxyFactory
ProxyFactory factory = new ProxyFactory();
// 2. 设置目标对象
UserService target = new UserServiceImpl();
factory.setTarget(target);
// 3. 添加增强
factory.addAdvice(new LogAroundAdvice());
// 4. 获取代理对象
UserService proxy = (UserService) factory.getProxy();
// 5. 使用代理
proxy.createUser("王五");5.3 ProxyFactory 内部调用链
ProxyFactory.getProxy() 的完整调用链:
ProxyFactory.getProxy()
└── ProxyCreatorSupport.createAopProxy()
└── DefaultAopProxyFactory.createAopProxy(config)
├── 判断条件 → new JdkDynamicAopProxy(config)
└── 判断条件 → new ObjenesisCglibAopProxy(config)5.4 JdkDynamicAopProxy.getProxy 源码
// org.springframework.aop.framework.JdkDynamicAopProxy
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler {
private final AdvisedSupport advised;
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
this.advised = config;
}
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
// 获取所有需要代理的接口
Class<?>[] proxiedInterfaces =
AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 调用 JDK 原生 Proxy 创建代理
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
// JdkDynamicAopProxy 自身就是 InvocationHandler
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// ... 方法拦截逻辑(详见下文)
}
}5.5 CglibAopProxy.getProxy 源码
// org.springframework.aop.framework.CglibAopProxy
class CglibAopProxy implements AopProxy {
private final AdvisedSupport advised;
@Override
public Object getProxy() {
return getProxy(null);
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
// ... 前置检查 ...
// 1. 创建 Enhancer
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(proxySuperClass); // 设置父类(目标类)
enhancer.setInterfaces(AopProxyUtils
.completeProxiedInterfaces(this.advised)); // 设置接口
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); // 命名策略
enhancer.setClassLoader(classLoader);
// 2. 设置 Callback 回调
Callback[] callbacks = getCallbacks(advised);
enhancer.setCallbacks(callbacks);
enhancer.setCallbackFilter(new ProxyCallbackFilter(advised));
// 3. 创建代理实例
return createProxyClassAndInstance(enhancer, advised);
}
}6. Advice / Pointcut / Advisor 接口体系
6.1 接口继承关系
Spring AOP 围绕三个核心接口展开:
Advice(标记接口)
├── BeforeAdvice
│ └── MethodBeforeAdvice
├── AfterAdvice
│ ├── AfterReturningAdvice
│ └── ThrowsAdvice
└── Interceptor(AOP Alliance)
└── MethodInterceptor
└── AroundAdvice(Spring 内部)
Pointcut(切点)
├── ClassFilter — 类级别匹配
└── MethodMatcher — 方法级别匹配(支持静态/动态匹配)
Advisor(通知器,将 Pointcut + Advice 组合)
├── PointcutAdvisor — 带切点的通知器
│ ├── AspectJPointcutAdvisor
│ ├── NameMatchMethodPointcutAdvisor
│ └── RegexpMethodPointcutAdvisor
└── IntroductionAdvisor — 引入型通知器6.2 Advice 接口源码
// org.aopalliance.aop.Advice (AOP Alliance 标准接口)
public interface Advice {
}
// org.springframework.aop.MethodBeforeAdvice
public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method method, Object[] args, @Nullable Object target)
throws Throwable;
}
// org.springframework.aop.AfterReturningAdvice
public interface AfterReturningAdvice extends AfterAdvice {
void afterReturning(@Nullable Object returnValue,
Method method, Object[] args,
@Nullable Object target) throws Throwable;
}
// org.aopalliance.intercept.MethodInterceptor (AOP Alliance 标准)
public interface MethodInterceptor extends Interceptor {
Object invoke(MethodInvocation invocation) throws Throwable;
}6.3 Pointcut 接口源码
// org.springframework.aop.Pointcut
public interface Pointcut {
// 类过滤器
ClassFilter getClassFilter();
// 方法匹配器
MethodMatcher getMethodMatcher();
// 匹配所有对象的 Pointcut 单例
Pointcut TRUE = TruePointcut.INSTANCE;
}
// org.springframework.aop.ClassFilter
public interface ClassFilter {
boolean matches(Class<?> clazz);
ClassFilter TRUE = TrueClassFilter.INSTANCE;
}
// org.springframework.aop.MethodMatcher
public interface MethodMatcher {
// 静态匹配:仅根据方法和目标类判断(无需方法参数)
boolean matches(Method method, @Nullable Class<?> targetClass);
// 是否为运行时匹配(动态匹配)
boolean isRuntime();
// 动态匹配:在静态匹配通过后,进一步检查运行时参数
boolean matches(Method method, @Nullable Class<?> targetClass,
Object... args);
MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
}静态匹配 vs 动态匹配:
// 静态匹配示例 — AspectJ 表达式切点(大多数情况)
public class AspectJExpressionPointcut implements Pointcut, ClassFilter, MethodMatcher {
private String expression; // e.g., "execution(* com.example.*.*(..))"
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 在代理创建时执行,仅匹配一次
return PointcutExpression.matchesMethodExecution(method).alwaysMatches();
}
@Override
public boolean isRuntime() {
return false; // 静态匹配,不检查参数
}
// 动态匹配不会被调用
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
throw new UnsupportedOperationException();
}
}
// 动态匹配示例 — 根据参数值决定
public class ArgsValueMatchPointcut extends StaticMethodMatcherPointcut {
private String requiredParamValue;
@Override
public boolean matches(Method method, Class<?> targetClass) {
return method.getName().startsWith("find"); // 先静态匹配
}
@Override
public boolean isRuntime() {
return true; // 需要运行时判断
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
// 运行时检查参数值
return args.length > 0 && requiredParamValue.equals(args[0]);
}
}6.4 Advisor 接口源码
// org.springframework.aop.Advisor
public interface Advisor {
// 获取通知(Advice)
Advice getAdvice();
// 是否为空(用于框架内部判断)
boolean isPerInstance();
}
// org.springframework.aop.PointcutAdvisor
public interface PointcutAdvisor extends Advisor {
// 获取切点
Pointcut getPointcut();
// 排序
@Override
default int getOrder() {
return 0;
}
}6.5 三者关系
Advisor(通知器)
├── 包含 1 个 Pointcut(切点:定义"在哪里切")
├── 包含 1 个 Advice(通知:定义"切什么逻辑")
└── 职责:将 Pointcut 与 Advice 组合为一个完整的切面配置
ProxyFactory 处理流程:
1. 获取所有注册的 Advisor
2. 遍历 Advisor,调用 Pointcut 匹配目标方法
3. 匹配成功 → 将 Advice 包装为拦截器链
4. 创建代理,使代理方法调用走拦截器链7. @EnableAspectJAutoProxy 注解源码
7.1 注解定义
// org.springframework.context.annotation.EnableAspectJAutoProxy
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class) // 关键:导入 Registrar
public @interface EnableAspectJAutoProxy {
// 是否强制使用 CGLIB 代理(proxyTargetClass)
@AliasFor("proxyTargetClass")
boolean value() default false;
@AliasFor("value")
boolean proxyTargetClass() default false;
// 是否暴露代理对象到 ThreadLocal(用于解决内部调用问题)
boolean exposeProxy() default false;
}7.2 AspectJAutoProxyRegistrar 源码
// org.springframework.context.annotation.AspectJAutoProxyRegistrar
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
// 注册 AnnotationAwareAspectJAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 处理 @EnableAspectJAutoProxy 的属性
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata,
EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
// 设置 proxyTargetClass
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
// 设置 exposeProxy
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}7.3 AnnotationAwareAspectJAutoProxyCreator 继承链
这个类是注解驱动 AOP 的核心,其继承关系如下:
BeanPostProcessor(后置处理器接口)
└── InstantiationAwareBeanPostProcessor
└── SmartInstantiationAwareBeanPostProcessor
└── AbstractAutoProxyCreator — 核心:在 Bean 初始化后创建代理
└── AbstractAdvisorAutoProxyCreator — 获取所有 Advisor
└── AspectJAwareAdvisorAutoProxyCreator — 排序与过滤
└── AnnotationAwareAspectJAutoProxyCreator — 解析 @AspectJ 注解工作流程:
// AbstractAutoProxyCreator.postProcessAfterInitialization
// 在 Bean 初始化完成后调用
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 核心方法: 包装 Bean 为代理
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
// wrapIfNecessary 核心逻辑
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 1. 获取当前 Bean 适用的所有 Advisor(切面)
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(
bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// 2. 创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 3. 缓存代理类
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return bean;
}7.4 Spring Boot 自动配置
Spring Boot 中,AOP 通过自动配置类启用:
// org.springframework.boot.autoconfigure.aop.AopAutoConfiguration
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true",
matchIfMissing = true)
public class AopAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Advice.class)
@EnableAspectJAutoProxy(proxyTargetClass = false)
static class JdkDynamicAutoProxyConfiguration { }
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class",
havingValue = "true", matchIfMissing = true)
@EnableAspectJAutoProxy(proxyTargetClass = true)
static class CglibAutoProxyConfiguration { }
}Spring Boot 2.x+ 默认使用 CGLIB 代理(proxyTargetClass=true)。
8. 源码分析:ProxyFactory.getProxy() 代理创建全流程
8.1 完整调用链路
以 @EnableAspectJAutoProxy + @Aspect 注解驱动为例,Bean 创建和代理生成的完整链路:
Spring 容器启动
└── AbstractApplicationContext.refresh()
└── finishBeanFactoryInitialization()
└── DefaultListableBeanFactory.preInstantiateSingletons()
└── AbstractBeanFactory.getBean()
└── AbstractAutowireCapableBeanFactory.doCreateBean()
├── createBeanInstance() → 实例化目标 Bean
├── populateBean() → 属性填充
├── initializeBean() → 初始化
│ ├── applyBeanPostProcessorsBeforeInitialization()
│ ├── invokeInitMethods() → @PostConstruct / InitializingBean
│ └── applyBeanPostProcessorsAfterInitialization()
│ └── AbstractAutoProxyCreator.postProcessAfterInitialization()
│ └── wrapIfNecessary() → 核心:决定是否需要代理
└── 返回代理对象(或原始 Bean)8.2 详细流程分解
步骤一:收集所有 Advisor
// AbstractAdvisorAutoProxyCreator
@Override
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY; // 没有匹配的切面,不创建代理
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 1. 获取容器中所有 Advisor(包含 @AspectJ 解析出的)
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 2. 筛选出匹配当前 Bean 的 Advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 3. 扩展(子类可覆写)
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 4. 排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}findCandidateAdvisors() 在 AnnotationAwareAspectJAutoProxyCreator 中的实现:
@Override
protected List<Advisor> findCandidateAdvisors() {
List<Advisor> advisors = super.findCandidateAdvisors(); // XML 配置的 Advisor
if (this.aspectJAdvisorsBuilder != null) {
// 解析所有 @AspectJ 注解的 Bean,生成 Advisor
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}步骤二:创建代理
// AbstractAutoProxyCreator
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
// 1. 创建 ProxyFactory
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 2. 设置代理目标类
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 3. 将 Advisor 添加到 ProxyFactory
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
// 4. 冻结配置(不允许后续修改)
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 5. 核心: 获取代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}步骤三:ProxyFactory.getProxy() 核心
// org.springframework.aop.framework.ProxyCreatorSupport
public class ProxyCreatorSupport extends AdvisedSupport {
private AopProxyFactory aopProxyFactory;
public ProxyCreatorSupport() {
// 默认使用 DefaultAopProxyFactory
this.aopProxyFactory = new DefaultAopProxyFactory();
}
// 子类 ProxyFactory 调用此方法
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 通过工厂创建 AopProxy
return getAopProxyFactory().createAopProxy(this);
}
}
// org.springframework.aop.framework.ProxyFactory
public class ProxyFactory extends ProxyCreatorSupport {
public Object getProxy(@Nullable ClassLoader classLoader) {
// 核心调用链
return createAopProxy().getProxy(classLoader);
}
}步骤四:DefaultAopProxyFactory 决策
// org.springframework.aop.framework.DefaultAopProxyFactory(已在前文展示)
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass()
|| hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("...");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
} else {
return new JdkDynamicAopProxy(config);
}
}步骤五:最终代理调用过程
JDK 动态代理的 invoke() 方法拦截链路:
// JdkDynamicAopProxy.invoke() — 精简版核心逻辑
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 1. 处理 equals/hashCode 等特殊方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { ... }
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { ... }
if (method.getDeclaringClass() == DecoratingProxy.class) { ... }
// 2. 获取目标对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 3. 核心: 获取当前方法的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {
// 无拦截器时直接反射调用
return AopUtils.invokeJoinpointUsingReflection(target, method, args);
} else {
// 4. 创建 MethodInvocation 并执行拦截器链
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
return invocation.proceed();
}
} finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
}
}步骤六:拦截器链执行
// ReflectiveMethodInvocation.proceed()
public Object proceed() throws Throwable {
// 从 currentInterceptorIndex 开始依次执行拦截器
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 所有拦截器已执行完毕,调用目标方法
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// 动态匹配:在运行时检查方法参数是否匹配
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
} else {
// 不匹配则跳过,执行下一个拦截器
return proceed();
}
} else {
// 静态匹配:直接执行拦截器
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}执行流程图解:
调用 proxy.doSomething()
│
├── 进入代理类的 doSomething()
│
├── JdkDynamicAopProxy.invoke() / CglibAopProxy.DynamicAdvisedInterceptor.intercept()
│ │
│ ├── 获取拦截器链: [ExposeInvocationInterceptor, AspectJAfterThrowingAdvice,
│ │ AfterReturningAdvice, AspectJMethodBeforeAdvice]
│ │
│ └── 创建 ReflectiveMethodInvocation
│ │
│ └── invocation.proceed()
│ │
│ ├── 索引 0: ExposeInvocationInterceptor.invoke()
│ │ └── invocation.proceed() → 调用下一个
│ │
│ ├── 索引 1: AspectJMethodBeforeAdvice.invoke()
│ │ ├── 执行 @Before 逻辑
│ │ └── invocation.proceed() → 调用下一个
│ │
│ ├── 索引 2: AfterReturningAdvice.invoke()
│ │ └── invocation.proceed() → 调用下一个
│ │
│ ├── 索引 3: AspectJAfterThrowingAdvice.invoke()
│ │ └── invocation.proceed() → 调用下一个
│ │
│ └── 索引 4(末尾): invokeJoinpoint()
│ └── 反射调用目标方法 target.doSomething()
│
└── 返回结果注意: 不同类型的 Advice 会被适配为统一的
MethodInterceptor接口。例如,MethodBeforeAdviceAdapter将MethodBeforeAdvice包装为MethodBeforeAdviceInterceptor:
// org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// @Before 通知在 proceed() 之前执行
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}