Spring事务源码分析
1.确定事务管理方式【注册BD】
- 启动注解导入一个TransactionManagementConfigurationSelector:
- 根据mode属性使用不同风格的事务管理方式。注册一个AutoProxyResitry
- 根据mode属性和proxyTargetClass属性用不同方法将之注册到容器。
观察开始事务注解导入了一个TransactionManagementConfigurationSelector:
观察TransactionManagementConfigurationSelector:
点进去AutoProxyRegistrar:
2.自定义属性读取
- 之前aop流程,bean初始化后置会创建代理对象,此过程需要找出方法增强器,创建代理【wrapIfNecessary】
- 寻找候选增强器,再从候选增强器种寻找到匹配项。从候选增强器种寻找到匹配项时
- 如果是引介增强器【IntroductionAdvisor】且满足过滤器,直接匹配
- 如果是切点增强器【PointcutAdvisor】,查看其切点是否匹配【canApplly】,
- 而Bean工厂事务属性源增强器【BeanFactoryTransationAttributeSourceAdviosr】在此分支。里面会提取事务的自定义属性
找增强器时:
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//寻找候选增强器
List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
//从候选增强器种寻找到匹配项
List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
this.extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
关注第二个寻找匹配项的方法,底层调用AopUtils.findAdvisorsThatCanApply,观察它:
如果是IntroductionAdvisor类型,并且可以应用到目标类【canApply】,添加到一个容器
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
} else {
List<Advisor> eligibleAdvisors = new ArrayList();
Iterator var3 = candidateAdvisors.iterator();
while(var3.hasNext()) {
Advisor candidate = (Advisor)var3.next();
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
Iterator var7 = candidateAdvisors.iterator();
while(var7.hasNext()) {
Advisor candidate = (Advisor)var7.next();
if (!(candidate instanceof IntroductionAdvisor) && canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
}
观察canApply方法:
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
//如果是引介增强器【IntroductionAdvisor】且满足过滤器
return ((IntroductionAdvisor)advisor).getClassFilter().matches(targetClass);
} else if (advisor instanceof PointcutAdvisor) {
//或者是切点增强器【PointcutAdvisor】类型
PointcutAdvisor pca = (PointcutAdvisor)advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
} else {
return true;
}
}
而Bean工厂事务属性源增强器【BeanFactoryTransationAttributeSourceAdviosr】是一个切点增强器【PointcutAdvisor】
所以走第二分支,调用getPointcut继续调用canApply方法
3.事务增强器【TransactionInterceptor】
- 获取事务属性和管理器,判断是声明式还是编程式事务,执行不同逻辑
- 如果是声明式事务,尝试获取创建一个【ReactiveTransactionSupport】
- 针对目标方法返回类型【Mono、Flux】来创建、提交、回滚事务
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, InvocationCallback invocation) throws Throwable {
TransactionAttributeSource tas = this.getTransactionAttributeSource();
//获取事务属性
TransactionAttribute txAttr = tas != null ? tas.getTransactionAttribute(method, targetClass) : null;
//获取事务管理器
TransactionManager tm = this.determineTransactionManager(txAttr);
if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
ReactiveTransactionSupport txSupport = (ReactiveTransactionSupport)this.transactionSupportCache.computeIfAbsent(method, (key) -> {
if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && TransactionAspectSupport.KotlinDelegate.isSuspend(method)) {
throw new TransactionUsageException("Unsupported annotated transaction on suspending function detected: " + method + ". Use TransactionalOperator.transactional extensions instead.");
} else {//如果不是Kotlin 类型或者不是挂起函数
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
//找不到对应的ReactiveAdapter 抛出异常
if (adapter == null) {
throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " + method.getReturnType());
} else {//找得到创建一个辅助类【ReactiveTransactionSupport】
return new ReactiveTransactionSupport(adapter);
}
}
});
return txSupport.invokeWithinTransaction(method, targetClass, invocation, txAttr, (ReactiveTransactionManager)tm);
} else {
。。。。。。//编程式事务处理
}
观察事务支持辅助类:
public Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, InvocationCallback invocation, @Nullable TransactionAttribute txAttr, ReactiveTransactionManager rtm) {
String joinpointIdentification = TransactionAspectSupport.this.methodIdentification(method, targetClass, txAttr);
return Mono.class.isAssignableFrom(method.getReturnType()) ? TransactionContextManager.currentContext().flatMap((context) -> {
return this.createTransactionIfNecessary(rtm, txAttr, joinpointIdentification).flatMap((it) -> {
try {
return Mono.usingWhen(Mono.just(it), (txInfo) -> {
try {
return (Mono)invocation.proceedWithInvocation();
} catch (Throwable var3) {
return Mono.error(var3);
}
}, this::commitTransactionAfterReturning, (txInfo, err) -> {
return Mono.empty();
}, this::commitTransactionAfterReturning).onErrorResume((ex) -> {
return this.completeTransactionAfterThrowing(it, ex).then(Mono.error(ex));
});
} catch (Throwable var4) {
return this.completeTransactionAfterThrowing(it, var4).then(Mono.error(var4));
}
});
}).subscriberContext(TransactionContextManager.getOrCreateContext()).subscriberContext(TransactionContextManager.getOrCreateContextHolder()) : this.adapter.fromPublisher(TransactionContextManager.currentContext().flatMapMany((context) -> {
return this.createTransactionIfNecessary(rtm, txAttr, joinpointIdentification).flatMapMany((it) -> {
try {
return Flux.usingWhen(Mono.just(it), (txInfo) -> {
try {
return this.adapter.toPublisher(invocation.proceedWithInvocation());
} catch (Throwable var4) {
return Mono.error(var4);
}
}, this::commitTransactionAfterReturning, (txInfo, ex) -> {
return Mono.empty();
}, this::commitTransactionAfterReturning).onErrorResume((ex) -> {
return this.completeTransactionAfterThrowing(it, ex).then(Mono.error(ex));
});
} catch (Throwable var4) {
return this.completeTransactionAfterThrowing(it, var4).then(Mono.error(var4));
}
});
}).subscriberContext(TransactionContextManager.getOrCreateContext()).subscriberContext(TransactionContextManager.getOrCreateContextHolder()));
}
4.总结
1.启动类注解引入了一个TransactionManagementConfigurationSelector
- 根据mode属性选择对应的事务管理方式
- 配置了一个AutoProxyRegistrar,再容器启动第二步将BD注册到容器
2.再bean初始化后置处理器的后置方法阶段,生成代理对象 - 创建代理时,会获取到事务增强器,
- 提供在目标方法开始前开启事务,结束后关闭事务,失败事务回滚等功能