第2篇-AOP代理——事务的'隐身衣'
约 5759 字大约 19 分钟
2026-05-24
四、AOP 代理的基本原理
要理解为什么 @Transactional 放在 private 方法上不生效,我们得先搞清楚:Spring 的 AOP 代理是怎么工作的?
4.1 代理模式的本质
代理模式,说白了就是:你以为你在调用目标对象的方法,其实你是在调用代理对象的方法。
你 ——> 代理对象 ——> 目标对象代理对象会在调用目标对象的方法之前和之后,做一些"额外"的事情(比如开启事务、提交事务)。
4.2 Spring 的两种代理方式
Spring AOP 支持两种代理方式:
| 代理方式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| JDK 动态代理 | 基于接口,运行时生成接口的实现类 | 无需额外依赖,JDK 自带 | 只能代理接口,不能代理类 |
| CGLIB 代理 | 基于继承,运行时生成目标类的子类 | 可以代理类(不需要接口) | 需要引入 CGLIB 依赖(Spring 已内置) |
那么问题来了:Spring Boot 默认使用哪种代理方式?
答案是:CGLIB 代理。
为什么?因为 Spring Boot 的 TransactionAutoConfiguration 中,CglibAutoProxyConfiguration 的 matchIfMissing = true!
// 类路径:org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = true) // 【核心】强制使用 CGLIB 代理
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class",
havingValue = "true", matchIfMissing = true) // 【核心】默认匹配!
public static class CglibAutoProxyConfiguration {
}五、JDK 动态代理 vs CGLIB 代理
5.1 JDK 动态代理
JDK 动态代理的核心是 java.lang.reflect.Proxy 类。
原理:运行时生成一个实现了指定接口的代理类,所有方法调用都会转发到 InvocationHandler.invoke() 方法。
// 类路径:java.lang.reflect.Proxy
public class Proxy implements java.io.Serializable {
/**
* 创建一个动态代理对象。
*
* @param loader 类加载器
* @param interfaces 要实现的接口列表
* @param h 调用处理器(所有方法调用都会转发到这里)
*/
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h) {
// ... 省略实现 ...
}
}Spring 对 JDK 动态代理的封装是 JdkDynamicAopProxy:
// 类路径:org.springframework.aop.framework.JdkDynamicAopProxy
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
private final AdvisedSupport advised;
/**
* 【核心方法】:拦截所有方法调用。
*
* 当调用代理对象的任何方法时,都会先走到这个方法!
*
* @param proxy 代理对象本身
* @param method 被调用的方法
* @param args 方法参数
*/
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.getTargetSource();
Object target = null;
try {
// 1. 处理 equals() 和 hashCode() 方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}
// 2. 获取目标对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 3. 【核心】:获取拦截器链
// 这个方法会返回:所有适用于当前方法的 Advice(包括 TransactionInterceptor)
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// 4. 如果拦截器链为空,直接调用目标方法
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
// 5. 如果拦截器链不为空,创建 MethodInvocation,并执行拦截器链
else {
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 【核心】:执行拦截器链
retVal = invocation.proceed();
}
return retVal;
}
finally {
// 6. 释放目标对象
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
}关键发现:
JDK 动态代理只能代理接口:
- 因为
Proxy.newProxyInstance()要求你传入接口列表 - 如果你的 Service 没有实现接口,JDK 动态代理就用不了
- 因为
所有方法调用都会先走到
invoke()方法:- 包括
toString()、equals()、hashCode()等 - 所以,
@Transactional放在接口方法上才生效,放在类方法上不生效(如果只用 JDK 动态代理的话)
- 包括
5.2 CGLIB 代理
CGLIB 代理的核心是 et.sf.cglib.proxy.Enhancer` 类。
原理:运行时生成一个继承了目标类的子类,重写所有非 final 的方法,在子类中"插入"拦截逻辑。
// 类路径:org.springframework.cglib.proxy.Enhancer
public class Enhancer extends AbstractClassGenerator {
/**
* 创建一个 CGLIB 代理对象。
*
* @param superclass 要继承的父类
* @param callbacks 回调数组(每个方法对应一个回调)
*/
public Object create() {
// ... 省略实现 ...
}
}Spring 对 CGLIB 代理的封装是 CglibAopProxy:
// 类路径:org.springframework.aop.framework.CglibAopProxy
class CglibAopProxy implements AopProxy, Serializable {
private final AdvisedSupport advised;
/**
* 【核心方法】:获取 CGLIB 回调数组。
*
* CGLIB 代理的核心就是:为每个方法分配一个回调(Callback)。
* 当调用方法时,会执行对应的回调。
*/
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// 1. 创建事务拦截器回调(AOP 回调)
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised.getInterceptorsAndDynamicInterceptionAdvice(),
this.advised);
// 2. 创建目标对象调用回调(直接调用目标方法,不经过拦截器链)
Callback targetInterceptor = new StaticUnadvisedExposedInterceptor(
this.advised.getTargetSource(), this.advised.getTargetClass());
// 3. 创建回调数组
Callback[] callbacks = new Callback[] {
aopInterceptor, // 0: AOP 拦截器回调(处理事务等)
targetInterceptor, // 1: 目标对象调用回调
NoOp.INSTANCE, // 2: 不重写(直接调用父类方法)
// ... 省略其他回调 ...
};
return callbacks;
}
/**
* CGLIB 拦截器(核心内部类)。
*
* 当调用代理对象的方法时,会执行这个拦截器的 intercept() 方法。
*/
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
/**
* 【核心方法】:拦截所有方法调用。
*
* @param proxy 代理对象
* @param method 被调用的方法
* @param args 方法参数
* @param methodProxy 方法代理(用于调用父类方法)
*/
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.getTargetSource();
Object target = null;
try {
// 1. 获取目标对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 2. 【核心】:获取拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// 3. 如果拦截器链为空,直接调用目标方法
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
// 4. 如果拦截器链不为空,创建 MethodInvocation,并执行拦截器链
else {
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
return retVal;
}
finally {
// 5. 释放目标对象
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
}
}关键发现:
CGLIB 代理可以代理类:
- 因为 CGLIB 生成的是目标类的子类
- 所以,即使你的 Service 没有实现接口,事务也能生效
CGLIB 代理不能代理 final 类或 final 方法:
- 因为 CGLIB 是通过继承来实现代理的
- 如果类是 final 的,就不能被继承;如果方法是 final 的,就不能被重写
- 所以,
@Transactional放在 final 方法上也不生效!
所有方法调用都会先走到
intercept()方法:- 包括 public 方法、protected 方法
- 但是,private 方法不会被拦截!
- 因为 CGLIB 是通过重写方法来实现代理的,而 private 方法不能被重写!
六、为什么 @Transactional 放在 private 方法上不生效?
现在,我们可以回答这个问题了:
6.1 如果你用的是 JDK 动态代理
JDK 动态代理只能代理接口方法。如果你的 Service 没有实现接口,JDK 动态代理就用不了。
如果你的 Service 实现了接口,那么 @Transactional 必须放在接口方法上,才能生效。
为什么? 因为 JDK 动态代理生成的代理类,只实现了接口方法,没有实现类方法。所以,即使你在类方法上加了 @Transactional,代理类也"看不见"这个注解。
而且,即使你把 publicMethodsOnly 设为 false,JDK 动态代理也代理不了类方法!
6.2 如果你用的是 CGLIB 代理(Spring Boot 默认)
CGLIB 代理是通过重写方法来实现代理的。但是,private 方法不能被重写!
所以,当你调用一个 private 方法时,CGLIB 代理的 intercept() 方法根本不会被调用,事务就不会生效。
而且,即使你把 publicMethodsOnly 设为 false,CGLIB 也拦截不了 private 方法!
因为 Java 语言规范规定:private 方法不能被子类重写。CGLIB 生成的子类,无法重写 private 方法。
6.3 总结:@Transactional 不生效的情况
同理,以下情况事务也不会生效:
@Transactional放在 private 方法上(Java 规定 private 方法不能被重写)@Transactional放在 final 方法上(Java 规定 final 方法不能被重写)@Transactional放在 static 方法上(static 方法属于类,不属于实例,不能被重写)- 同一个类中,方法 A 调用方法 B(方法 B 上有
@Transactional)- 因为 this 调用不会经过代理对象!
- 解决方法:用
AopContext.currentProxy()获取代理对象,然后通过代理对象调用方法 B
七、TransactionInterceptor 是如何被"织入"到代理对象中的?
现在,我们来看看:Spring 是如何把 TransactionInterceptor 织入到代理对象中的?
7.0 精细化流程:从 BeanPostProcessor 到代理对象
在讲解具体实现之前,让我们先梳理一下完整的代理创建流程。这个流程涉及多个核心类的协作:
Spring 容器启动
↓
@EnableTransactionManagement 导入 AutoProxyRegistrar
↓
AutoProxyRegistrar 注册 InfrastructureAdvisorAutoProxyCreator(BeanPostProcessor)
↓
InfrastructureAdvisorAutoProxyCreator 注册 TransactionInterceptor + TransactionAttributeSourceAdvisor
↓
容器创建普通 Bean(比如 UserService)
↓
【核心】BeanPostProcessor.postProcessAfterInitialization() 被调用
↓
【核心】AbstractAutoProxyCreator.wrapIfNecessary() 判断是否需要代理
↓
【核心】AbstractAdvisorAutoProxyCreator.findEligibleAdvisors() 查找符合条件的 Advisor
↓
├→ TransactionAttributeSourcePointcut.matches() 检查类和方法
│ ↓
│ ├→ ClassFilter 检查类是否匹配
│ └→ MethodMatcher 检查方法是否有 @Transactional
│
└→ SpringTransactionAnnotationParser 解析 @Transactional 注解
↓
【核心】AbstractAutoProxyCreator.createProxy() 创建代理对象
↓
返回代理对象,替换原始 Bean7.1 Spring Boot 自动配置入口
在 Spring Boot 环境中,一切都是自动配置的。事务代理的创建也不例外。让我看看 TransactionAutoConfiguration:
// 类路径:org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = true) // 【核心】强制使用 CGLIB 代理
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class",
havingValue = "true", matchIfMissing = true) // 【核心】默认匹配!
public class TransactionAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public TransactionInterceptor transactionInterceptor(
TransactionAttributeSource transactionAttributeSource) {
// 【核心】创建 TransactionInterceptor
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
return interceptor;
}
@Bean
@ConditionalOnMissingBean
public TransactionAttributeSource transactionAttributeSource() {
// 【核心】创建 AnnotationTransactionAttributeSource
return new AnnotationTransactionAttributeSource();
}
@Configuration
@ConditionalOnClass(name = "org.springframework.transaction.annotation.EnableTransactionManagement")
@ConditionalOnProperty(prefix = "spring.tx", name = "enabled", havingValue = "true", matchIfMissing = true)
public static class EnableTransactionManagementConfiguration {
@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class",
havingValue = "true", matchIfMissing = true)
protected static class CglibAutoProxyConfiguration {
// 【核心】注册 InfrastructureAdvisorAutoProxyCreator
}
}
}关键发现:
- Spring Boot 默认启用事务:
matchIfMissing = true意味着即使不配置,也会启用 - 强制使用 CGLIB 代理:
proxyTargetClass = true - 自动注册核心组件:
TransactionInterceptor- 事务拦截器TransactionAttributeSource- 事务属性源InfrastructureAdvisorAutoProxyCreator- 自动代理创建器
7.2 Advisor 的组合关系
在 Spring 事务体系中,TransactionAttributeSourceAdvisor 是一个核心的 Advisor,它组合了切点和通知:
// 类路径:org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor
public class TransactionAttributeSourceAdvisor extends AbstractPointcutAdvisor {
// 【核心】关联的 TransactionInterceptor(通知)
@Nullable
private TransactionInterceptor transactionInterceptor;
// 【核心】关联的 TransactionAttributeSourcePointcut(切点)
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
// 【核心】从 TransactionInterceptor 获取 TransactionAttributeSource
return (transactionInterceptor != null ?
transactionInterceptor.getTransactionAttributeSource() : null);
}
};
// 【核心】返回通知(TransactionInterceptor)
@Override
public Advice getAdvice() {
Assert.state(this.transactionInterceptor != null, "No TransactionInterceptor set");
return this.transactionInterceptor;
}
// 【核心】返回切点(TransactionAttributeSourcePointcut)
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}关键发现:
TransactionAttributeSourceAdvisor= 切点 + 通知:- 切点:
TransactionAttributeSourcePointcut- 决定哪些类/方法需要被拦截 - 通知:
TransactionInterceptor- 决定拦截后做什么(开启事务、提交、回滚)
- 切点:
切点判断流程:
调用方法时 ↓ TransactionAttributeSourcePointcut.matches() ↓ 检查 TransactionAttributeSource.getTransactionAttribute() ↓ 如果返回非 null,说明这个方法需要事务
7.3 切点匹配:TransactionAttributeSourcePointcut
TransactionAttributeSourcePointcut 是事务代理的切点实现。它决定了哪些类和方法需要被代理:
// 类路径:org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut
implements Serializable {
protected TransactionAttributeSourcePointcut() {
// 【核心】设置类过滤器
setClassFilter(new TransactionAttributeSourceClassFilter());
}
// 【核心】方法匹配:检查方法是否有事务属性
@Override
public boolean matches(Method method, Class<?> targetClass) {
TransactionAttributeSource tas = getTransactionAttributeSource();
// 【核心】如果能获取到事务属性,说明这个方法需要事务
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
// 【核心】类过滤器:过滤不需要检查的类
private class TransactionAttributeSourceClassFilter implements ClassFilter {
@Override
public boolean matches(Class<?> clazz) {
// 【核心】排除事务相关的类
if (TransactionalProxy.class.isAssignableFrom(clazz) ||
TransactionManager.class.isAssignableFrom(clazz) ||
PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
// 【核心】调用 TransactionAttributeSource 判断是否需要检查
return (tas == null || tas.isCandidateClass(clazz));
}
}
}关键发现:
切点匹配分两步:
- 第一步:类过滤(ClassFilter)- 快速排除明显不需要代理的类
- 第二步:方法匹配(MethodMatcher)- 精确检查方法是否有
@Transactional
类过滤器的优化:
- 排除
TransactionManager相关类(避免自我代理) - 排除
PersistenceExceptionTranslator相关类 - 调用
TransactionAttributeSource.isCandidateClass()做进一步过滤
- 排除
方法匹配的核心:
- 调用
TransactionAttributeSource.getTransactionAttribute() - 如果返回非 null,说明方法上有
@Transactional注解
- 调用
7.4 事务属性解析:AbstractFallbackTransactionAttributeSource
AbstractFallbackTransactionAttributeSource 是事务属性解析的核心基类。它实现了多级回退查找机制:
// 类路径:org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource
public abstract class AbstractFallbackTransactionAttributeSource
implements TransactionAttributeSource, EmbeddedValueResolverAware {
// 【核心】事务属性缓存(key = method + targetClass)
private final Map<Object, TransactionAttribute> attributeCache =
new ConcurrentHashMap<>(1024);
// 【核心】获取事务属性(带缓存)
@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// 1. 忽略 Object 类的方法
if (method.getDeclaringClass() == Object.class) {
return null;
}
// 2. 【核心】先从缓存中获取
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// 缓存命中,直接返回
return (cached == NULL_TRANSACTION_ATTRIBUTE ? null : cached);
}
// 3. 【核心】计算事务属性
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// 4. 【核心】存入缓存
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
} else {
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
// 【核心】计算事务属性(四级回退查找)
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// 1. 【核心】检查方法修饰符(非 public 方法直接返回 null)
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null; // private/protected 方法直接返回 null
}
// 2. 获取最具体的方法(处理继承情况)
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// 3. 【核心】第一级查找:方法上的注解
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
// 4. 【核心】第二级查找:类上的注解
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
// 5. 【核心】第三级查找:接口方法上的注解(针对代理)
if (specificMethod != method) {
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// 6. 【核心】第四级查找:接口类上的注解
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null; // 找不到,返回 null
}
// 【核心】是否只允许 public 方法
protected boolean allowPublicMethodsOnly() {
return false; // 默认:允许所有方法
}
}关键发现:
缓存机制:
- 使用
ConcurrentHashMap存储事务属性 - 避免重复计算,提高性能
- 使用
四级回退查找机制:
- 第一级:具体方法上的
@Transactional注解 - 第二级:类上的
@Transactional注解 - 第三级:接口方法上的
@Transactional注解 - 第四级:接口类上的
@Transactional注解
- 第一级:具体方法上的
方法修饰符检查:
allowPublicMethodsOnly()返回true时,非 public 方法直接返回 null
7.5 注解解析:AnnotationTransactionAttributeSource
AnnotationTransactionAttributeSource 是 AbstractFallbackTransactionAttributeSource 的实现类,负责解析 @Transactional 注解:
// 类路径:org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
implements Serializable {
private final boolean publicMethodsOnly;
private final Set<TransactionAnnotationParser> annotationParsers;
public AnnotationTransactionAttributeSource() {
this(true); // 【核心】默认:publicMethodsOnly = true
}
// 【核心】重写:返回 true(只允许 public 方法)
@Override
protected boolean allowPublicMethodsOnly() {
return this.publicMethodsOnly; // 默认:true
}
// 【核心】查找方法上的事务属性
@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Method method) {
return determineTransactionAttribute(method);
}
// 【核心】查找类上的事务属性
@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
return determineTransactionAttribute(clazz);
}
// 【核心】解析注解
@Nullable
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
TransactionAttribute attr = parser.parseTransactionAnnotation(element);
if (attr != null) {
return attr; // 【核心】找到注解,返回事务属性
}
}
return null; // 没找到注解,返回 null
}
}7.6 注解解析器:SpringTransactionAnnotationParser
SpringTransactionAnnotationParser 是真正解析 @Transactional 注解的类:
// 类路径:org.springframework.transaction.annotation.SpringTransactionAnnotationParser
public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
// 【核心】解析 @Transactional 注解
@Override
@Nullable
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
// 使用 Spring 的注解工具解析注解
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
return null;
}
// 【核心】将注解属性转换为事务属性对象
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
// 解析传播行为
Propagation propagation = attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());
// 解析隔离级别
Isolation isolation = attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
// 解析超时
rbta.setTimeout(attributes.getNumber("timeout").intValue());
// 解析只读标记
rbta.setReadOnly(attributes.getBoolean("readOnly"));
// 解析回滚规则
List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
rbta.setRollbackRules(rollbackRules);
return rbta;
}
}7.7 拦截器链的组装:AbstractAdvisorAutoProxyCreator
AbstractAdvisorAutoProxyCreator 是自动代理创建器的核心实现。它负责查找符合条件的 Advisor:
// 类路径:org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
// 【核心】获取适用于 Bean 的 Advisor 列表
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 【核心】查找符合条件的 Advisor
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY; // 没有 Advisor,不需要代理
}
return advisors.toArray();
}
// 【核心】查找符合条件的 Advisor
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 1. 获取所有候选 Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 2. 【核心】过滤出适用于当前 Bean 的 Advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(
candidateAdvisors, beanClass, beanName);
// 3. 扩展 Advisor 列表
extendAdvisors(eligibleAdvisors);
// 4. 排序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
// 【核心】过滤 Advisor(使用 AopUtils)
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 【核心】使用 AopUtils 过滤 Advisor
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
}7.8 Advisor 匹配:AopUtils.findAdvisorsThatCanApply
AopUtils.findAdvisorsThatCanApply() 是匹配 Advisor 和 Bean 的核心方法:
// 类路径:org.springframework.aop.support.AopUtils
public static List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<>();
// 1. 先处理引介通知(IntroductionAdvisor)
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
if (canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
}
// 2. 【核心】处理普通通知(包括 TransactionAttributeSourceAdvisor)
List<Advisor> eligibleAdvisors1 = new LinkedList<>();
for (Advisor candidate : candidateAdvisors) {
if (!(candidate instanceof IntroductionAdvisor)) {
// 【核心】调用 canApply() 进行匹配
if (canApply(candidate, clazz)) {
eligibleAdvisors1.add(candidate);
}
}
}
eligibleAdvisors.addAll(eligibleAdvisors1);
return eligibleAdvisors;
}
// 【核心】检查 Advisor 是否适用于类
public static boolean canApply(Advisor advisor, Class<?> targetClass) {
if (advisor instanceof IntroductionAdvisor) {
// 引介通知的处理
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
// 【核心】普通通知的处理
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass);
}
else {
// 没有切点的通知,适用于所有类
return true;
}
}
// 【核心】检查切点是否适用于类
public static boolean canApply(Pointcut pointcut, Class<?> targetClass) {
// 1. 类过滤
if (!pointcut.getClassFilter().matches(targetClass)) {
return false; // 类不匹配,直接返回 false
}
// 2. 如果是 IntroductionAwarePointcutAdvisor,还需要检查方法
if (pointcut instanceof IntroductionAwarePointcutAdvisor) {
return ((IntroductionAwarePointcutAdvisor) pointcut)
.getPointcut().getMethodMatcher()
.matches(new TargetClassMethod(targetClass)) != MethodMatcher.TRUE;
}
return true; // 类匹配,返回 true
}7.9 整体协作流程图
现在,让我们用一张图来总结整个代理创建过程:
┌─────────────────────────────────────────────────────────────────┐
│ Spring 容器启动 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ @EnableTransactionManagement → AutoProxyRegistrar │
│ → 注册 InfrastructureAdvisorAutoProxyCreator │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ TransactionAutoConfiguration │
│ → 注册 TransactionInterceptor │
│ → 注册 TransactionAttributeSource │
│ → 注册 TransactionAttributeSourceAdvisor │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 创建普通 Bean(比如 UserService) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 【核心】BeanPostProcessor.postProcessAfterInitialization() │
│ → AbstractAutoProxyCreator.postProcessAfterInitialization() │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 【核心】wrapIfNecessary() │
│ → isInfrastructureClass() 排除基础设施类 │
│ → getAdvicesAndAdvisorsForBean() 获取 Advisor │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 【核心】AbstractAdvisorAutoProxyCreator.findEligibleAdvisors() │
│ → findCandidateAdvisors() 获取所有候选 Advisor │
│ → findAdvisorsThatCanApply() 过滤 Advisor │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 【核心】AopUtils.findAdvisorsThatCanApply() │
│ → 对每个 Advisor 调用 canApply() │
│ → TransactionAttributeSourceAdvisor.canApply() │
│ → TransactionAttributeSourcePointcut.getClassFilter() │
│ → TransactionAttributeSourcePointcut.matches() │
│ → TransactionAttributeSource.getTransactionAttribute() │
│ → AbstractFallbackTransactionAttributeSource │
│ → SpringTransactionAnnotationParser │
│ → parseTransactionAnnotation() │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 【核心】createProxy() │
│ → ProxyFactory.addAdvisors() 添加 Advisor │
│ → ProxyFactory.getProxy() 创建代理对象 │
│ → JdkDynamicAopProxy 或 CglibAopProxy │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 返回代理对象,替换原始 Bean │
└─────────────────────────────────────────────────────────────────┘7.10 调用时的拦截流程
当调用代理对象的方法时,会触发以下流程:
调用 userService.createUser()
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ JdkDynamicAopProxy.invoke() 或 CglibAopProxy.intercept() │
│ → 获取拦截器链 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ ReflectiveMethodInvocation.proceed() │
│ → 依次执行拦截器链中的拦截器 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ TransactionInterceptor.invoke() │
│ → invokeWithinTransaction() │
│ → 获取事务属性 │
│ → 获取事务管理器 │
│ → 创建事务 │
│ → 执行目标方法 │
│ → 提交/回滚 │
└─────────────────────────────────────────────────────────────────┘7.11 核心类汇总
| 类名 | 职责 | 关键方法 |
|---|---|---|
AbstractAutoProxyCreator | BeanPostProcessor,实现代理创建入口 | postProcessAfterInitialization() |
AbstractAdvisorAutoProxyCreator | 查找符合条件的 Advisor | findEligibleAdvisors() |
InfrastructureAdvisorAutoProxyCreator | 只代理基础设施 Bean | isEligibleAdvisorBean() |
TransactionAttributeSourceAdvisor | 事务 Advisor(切点 + 通知) | getPointcut(), getAdvice() |
TransactionAttributeSourcePointcut | 事务切点(类/方法匹配) | matches() |
AbstractFallbackTransactionAttributeSource | 事务属性解析基类(四级回退) | getTransactionAttribute() |
AnnotationTransactionAttributeSource | 注解解析实现 | findTransactionAttribute() |
SpringTransactionAnnotationParser | 注解解析器 | parseTransactionAnnotation() |
TransactionInterceptor | 事务拦截器 | invoke() |
7.12 源码导航汇总
为了方便你深入研究,这里汇总了所有关键类的源码路径:
| 类名 | 源码路径 |
|---|---|
AbstractAutoProxyCreator | spring-aop/.../autoproxy/AbstractAutoProxyCreator.java |
AbstractAdvisorAutoProxyCreator | spring-aop/.../autoproxy/AbstractAdvisorAutoProxyCreator.java |
InfrastructureAdvisorAutoProxyCreator | spring-aop/.../autoproxy/InfrastructureAdvisorAutoProxyCreator.java |
TransactionAttributeSourceAdvisor | spring-tx/.../interceptor/TransactionAttributeSourceAdvisor.java |
TransactionAttributeSourcePointcut | spring-tx/.../interceptor/TransactionAttributeSourcePointcut.java |
AbstractFallbackTransactionAttributeSource | spring-tx/.../interceptor/AbstractFallbackTransactionAttributeSource.java |
AnnotationTransactionAttributeSource | spring-tx/.../annotation/AnnotationTransactionAttributeSource.java |
SpringTransactionAnnotationParser | spring-tx/.../annotation/SpringTransactionAnnotationParser.java |
TransactionInterceptor | spring-tx/.../interceptor/TransactionInterceptor.java |
TransactionAspectSupport | spring-tx/.../interceptor/TransactionAspectSupport.java |
7.13 谁注册了 AbstractAutoProxyCreator?
你可能会问:"AbstractAutoProxyCreator 是一个抽象类,那是谁注册了它的子类呢?"
答案是:AutoProxyRegistrar。
还记得我们在第一篇文章中讲过的 @EnableTransactionManagement 吗?它导入了 TransactionManagementConfigurationSelector,而这个 Selector 又会导入 AutoProxyRegistrar。
AutoProxyRegistrar 会注册一个 InfrastructureAdvisorAutoProxyCreator(它是 AbstractAdvisorAutoProxyCreator 的子类,而 AbstractAdvisorAutoProxyCreator 又是 AbstractAutoProxyCreator 的子类)。
// 类路径:org.springframework.context.annotation.AutoProxyRegistrar
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* 【核心方法】:注册自动代理创建器。
*
* 这个方法会:
* 1. 判断 mode 是否为 PROXY
* 2. 如果是,注册 InfrastructureAdvisorAutoProxyCreator
* 3. 如果 proxyTargetClass 为 true,强制使用 CGLIB 代理
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
// ... 省略实现 ...
if (mode == AdviceMode.PROXY) {
// 【核心】:注册 InfrastructureAdvisorAutoProxyCreator
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
// 【核心】:强制使用 CGLIB 代理
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
}
}
}八、InfrastructureAdvisorAutoProxyCreator 的作用
InfrastructureAdvisorAutoProxyCreator 是 AbstractAdvisorAutoProxyCreator 的子类。
它的特殊之处在于:它只代理"基础设施 Bean"(role = ROLE_INFRASTRUCTURE)。
// 类路径:org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator
public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
@Nullable
private ConfigurableListableBeanFactory beanFactory;
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.initBeanFactory(beanFactory);
this.beanFactory = beanFactory;
}
/**
* 【核心方法】:判断一个 Advisor Bean 是否合格。
*
* 这个方法会:
* 1. 判断这个 Advisor Bean 的 role 是否为 ROLE_INFRASTRUCTURE
* 2. 如果是,才认为是合格的 Advisor
*
* 【意义】:这样,就只会代理那些"基础设施 Bean"(比如事务 Advisor),
* 而不会代理用户自定义的 Advisor。
*/
@Override
protected boolean isEligibleAdvisorBean(String beanName) {
return (this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) &&
this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
}
}关键发现:
InfrastructureAdvisorAutoProxyCreator只会代理"基础设施 Bean":- 什么是"基础设施 Bean"?就是那些 role =
ROLE_INFRASTRUCTURE的 Bean - 比如:
TransactionInterceptor、BeanFactoryTransactionAttributeSourceAdvisor等 - 这些 Bean 都是 Spring 事务基础设施的一部分
- 什么是"基础设施 Bean"?就是那些 role =
这样做的好处是什么?
- 避免代理用户自定义的 Advisor
- 提高性能(不需要检查所有的 Advisor)
九、Spring Boot 默认使用哪个代理?
现在,我们可以回答这个问题了:
Spring Boot 默认使用 CGLIB 代理。
为什么?因为 TransactionAutoConfiguration 中的 CglibAutoProxyConfiguration 的 matchIfMissing = true!
# application.yml
spring:
aop:
proxy-target-class: true # 默认值就是 true,可以省略如果你想用 JDK 动态代理,可以这样配置:
# application.yml
spring:
aop:
proxy-target-class: false # 使用 JDK 动态代理十、扩展点总结
在这篇文章中,我们提到了以下几个扩展点:
| 扩展点 | 场景 | 如何扩展 |
|---|---|---|
| 自定义代理方式 | 你想强制使用 JDK 动态代理或 CGLIB 代理 | 配置 spring.aop.proxy-target-class 属性 |
| 自定义 Advisor | 你想添加自己的 Advisor(比如日志 Advisor) | 实现 Advisor 接口,并注册为 Bean |
| 自定义代理创建器 | 你想完全控制代理创建逻辑 | 继承 AbstractAutoProxyCreator,并重写相关方法 |
| 暴露代理对象 | 你想在目标对象中访问代理对象(解决 this 调用问题) | 设置 exposeProxy = true,然后使用 AopContext.currentProxy() |
十一、小结与伏笔
好了,到这里,我们已经把 AOP 代理的"神秘面纱"揭开了。
让我们来回顾一下整个流程:
- Spring 容器启动时,
AutoProxyRegistrar会注册InfrastructureAdvisorAutoProxyCreator InfrastructureAdvisorAutoProxyCreator会在每个 Bean 初始化后,判断这个 Bean 是否需要被代理- 如果需要代理,创建代理对象(JDK 动态代理或 CGLIB 代理)
- 把
TransactionInterceptor添加到代理对象的拦截器链中 - 当调用代理对象的方法时,
TransactionInterceptor.invoke()会被执行 invoke()方法调用了父类TransactionAspectSupport.invokeWithinTransaction()方法- 这个方法才是事务管理的真正核心!
🔮 伏笔:事务管理器是如何"拿到"连接的?
你可能会注意到,TransactionInterceptor 需要一个 PlatformTransactionManager(事务管理器)。
而 PlatformTransactionManager 需要一个 DataSource(数据源)。
那么问题来了:
- 事务管理器是如何从数据源获取连接的?
- 连接是如何被"绑定"到当前线程的?
- MyBatis 执行 SQL 时,是如何获取到这个连接的?
这些问题,我们会在下一篇文章(系列一第3篇:事务传播机制源码深度解析)中继续讲解。
下一篇预告:《Spring 事务(三):事务传播机制源码深度解析》
在这篇文章中,我们会讲解:
- 7 种传播行为的源码实现
handleExistingTransaction()方法详解- 嵌套事务的创建与回滚
- 事务挂起(suspend)与恢复(resume)的底层实现
写在最后:这篇文章比较长,但我觉得值得。因为只有当理解了 AOP 代理的原理,你才能真正理解为什么
@Transactional放在 private 方法上不生效。如果你有什么疑问,欢迎留言讨论!