共计 2323 个字符,预计需要花费 6 分钟才能阅读完成。
一、前言
Spring AOP(Aspect-Oriented Programming,面向切面编程)是 Spring 框架中实现横切逻辑(如事务、安全、日志)不可或缺的模块。
容易遇到的问题:
- 为什么有时代理类是
$Proxy0
,有时是com.xx$$EnhancerBySpringCGLIB
? - 接口与类的代理方式有什么区别?
- AOP 是怎么织入代码的?Spring 是何时生成代理对象的?
- AOP 的执行链是如何维护的?
本篇文章将以源码为主线,全面解析 Spring AOP 的原理,深入理解 JDK 动态代理与 CGLIB 的实现机制。
二、Spring AOP 是什么?
Spring AOP 是基于 代理模式 实现的,将横切逻辑织入目标对象的执行流程中,核心是对目标 Bean 生成代理对象。
关键点:
- 本质是一个 动态代理对象(实现了目标类的接口或子类)
- 通过 AOP 拦截器链(
MethodInterceptor
)来增强目标方法 - 默认采用 运行时增强(非编译期织入)
三、Spring AOP 代理创建过程
1.入口注解@EnableAspectJAutoProxy
@Configuration
@EnableAspectJAutoProxy
public class AopConfig { … }
这个注解的作用是启用基于注解的 AOP 功能,它最终引入了:
@Import(AspectJAutoProxyRegistrar.class)
注册了核心组件:
AnnotationAwareAspectJAutoProxyCreator
它是一个实现了 BeanPostProcessor
接口的类,用来在 Bean 初始化后判断是否需要生成代理。
2. 关键类:AnnotationAwareAspectJAutoProxyCreator
其中核心方法是:
public Object postProcessAfterInitialization(Object bean, String beanName) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
3.wrapIfNecessary 方法
判断当前 bean 是否需要增强,如果需要则调用 createProxy()
创建代理对象:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
return bean;
}
// 获取切面匹配的通知器(Advisor)
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(...);
if (specificInterceptors != DO_NOT_PROXY) {
return createProxy(bean.getClass(), beanName, specificInterceptors, ...);
}
return bean;
}
四、JDK 动态代理与 CGLIB 区别与源码分析
Spring AOP 默认会根据目标类是否实现了接口自动选择:
场景 | 代理方式 | 关键类 |
---|---|---|
目标类实现了接口 | 使用 JDK 动态代理 | JdkDynamicAopProxy |
目标类未实现接口 | 使用 CGLIB 代理 | CglibAopProxy |
五、拦截器链执行流程(重要)
无论是 JDK 代理还是 CGLIB,Spring 最终都构建一个拦截器链(MethodInterceptor
),然后顺序执行。
流程如下:
MethodInterceptor1 -> MethodInterceptor2 -> … -> 目标方法执行 -> 返回结果
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptors.size() - 1) {
return invokeJoinpoint(); // 调用目标方法
}
MethodInterceptor interceptor = this.interceptors.get(++currentInterceptorIndex);
return interceptor.invoke(this);
}
常见的拦截器有:
TransactionInterceptor
(事务)MethodBeforeAdviceInterceptor
(前置通知)AspectJAfterReturningAdvice
(后置通知)AspectJAfterThrowingAdvice
(异常通知)
六、完整执行流程图
(还没画完 后续补上)
七、总结
Spring AOP 为我们提供了极为灵活和强大的面向切面能力。深入理解其代理机制、拦截器执行流程、动态代理原理,不仅有助于我们写出高质量、可维护的业务代码,更能让我们在调试与排障中得心应手。
八、关注后续专栏
本文是《Spring 源码解析系列》专栏的第 3 篇,后续将发布:
- 《Spring 中的事件监听机制(ApplicationEvent)源码与实战》
- 《Spring Bean 的循环依赖原理(三级缓存)深入分析》
附录:参考源码位置
AnnotationAwareAspectJAutoProxyCreator.java
JdkDynamicAopProxy.java
CglibAopProxy.java
ReflectiveMethodInvocation.java
MethodInterceptor.java
如果本文对你有帮助,欢迎点赞、评论、收藏!我是 李卷卷,专注Java相关知识输出。感谢阅读!