CobarClient支持Spring3.x的分析
程序员文章站
2022-05-25 08:02:32
...
[size=large][b]问题:[/b][/size]
CobarClient(https://github.com/alibaba/cobarclient 下面简称CC)在Spring2.5下的配置事务管理器
但是在Spring3.x下面这样配置,在启动事务的时候,会有错误
[b][size=large]检查原因:[/size][/b]
启动事务的时候,TransactionManager会调用getTransaction方法初始化事务,这里面会调用子类的doBegin方法
而MultipleDataSourcesTransactionManager(CC实现的子类)的doBegin方法中将调用各个实际数据源DataSourceTransactionManager的getTransaction方法,从而开启各个数据源的事务
ps:其实最好做法是调用各个实际数据源的doBegin方法,但是因为这个方法是protected的,无法在外部调用,只能退而求其次,调用getTransacation方法。
但是在新版spring下面,MultipleDataSourcesTransactionManager的抽象类AbstractPlatformTransactionManager进行了重写
getTransaction方法内部在调用doBegin之后又调用了prepareSynchronization方法
这个方法会调用initSynchronization初始化一个ThreadLocal变量synchronizations
在初始化之前会检查该变量是否已经初始化了,如果出现就报错。
而CC的doBegin是调用了getTransaction,所以该变量会初始化多次,所以导致无法通过检查。
但是如果我们把transactionManager 的transactionSynchronization设置为SYNCHRONIZATION_NEVER,就会避免initSynchronization重复初始化问题,
因为MultipleDataSourcesTransactionManager的isNewSynchronization属性为false,initSynchronization就不会执行。
[b][size=large]Spring3.x中设置如下[/size][/b]:
TransactionSynchronization的含义:
下面摘自网上的描述
[i]TransactionSynchronization是可以注册到事务处理过程中的回调接口。它就像是事务处理的事件监听器,当事务处理的某些规定时点发生时,会调用TransactionSynchronization上的一些方法来执行相应的回调逻辑,如在事务完成后清理相应的系统资源等操作。Spring事务抽象框架所定义的TransactionSynchronization类似于JTA规范的javax.transaction.Synchronization,但比JTA的Synchronization提供了更多的回调方法,允许我们对事务的处理添加更多的回调逻辑。[/i]
看起来TransactionSynchronization应该是类似AOP的一种对事务事件的回调,不过我没有用过。
[size=large][b]可能导致的问题[/b][/size]:
个人分析-不会,因为我们屏蔽的只是CC的MultipleDataSourcesTransactionManager的transactionSynchronization属性,而实际的数据源事务管理器的transactionSynchronization仍然是默认的SYNCHRONIZATION_ALWAYS。
总结一下,可以这样认为,我们在CC中不支持transactionSynchronization特性。
其实我们对MultipleDataSourcesTransactionManager设置的属性都没有应用到的数据源事务管理器DataSourcesTransactionManager上
CobarClient(https://github.com/alibaba/cobarclient 下面简称CC)在Spring2.5下的配置事务管理器
<bean id="transactionManager"
class="com.alibaba.cobar.client.transaction.MultipleDataSourcesTransactionManager">
<property name="cobarDataSourceService" ref="dataSources" />
<property name="globalRollbackOnParticipationFailure" value="true" />
</bean>
但是在Spring3.x下面这样配置,在启动事务的时候,会有错误
java.lang.IllegalStateException: Cannot activate transaction synchronization - already active
at org.springframework.transaction.support.TransactionSynchronizationManager.initSynchronization(TransactionSynchronizationManager.java:270)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.prepareSynchronization(AbstractPlatformTransactionManager.java:537)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:417)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:255)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy10.createOffersInBatch(Unknown Source)
at com.alibaba.cobar.client.transaction.MultipleDataSourcesTransactionManagerTest.testOfferCreationOnMultipleShardsWithNormallyOfferService(MultipleDataSourcesTransactionManagerTest.java:94)
[b][size=large]检查原因:[/size][/b]
启动事务的时候,TransactionManager会调用getTransaction方法初始化事务,这里面会调用子类的doBegin方法
而MultipleDataSourcesTransactionManager(CC实现的子类)的doBegin方法中将调用各个实际数据源DataSourceTransactionManager的getTransaction方法,从而开启各个数据源的事务
List<DefaultTransactionStatus> list = (List<DefaultTransactionStatus>) transactionObject;
for (PlatformTransactionManager transactionManager : transactionManagers) {
DefaultTransactionStatus element = (DefaultTransactionStatus) transactionManager
.getTransaction(transactionDefinition);
list.add(element);
}
ps:其实最好做法是调用各个实际数据源的doBegin方法,但是因为这个方法是protected的,无法在外部调用,只能退而求其次,调用getTransacation方法。
但是在新版spring下面,MultipleDataSourcesTransactionManager的抽象类AbstractPlatformTransactionManager进行了重写
getTransaction方法内部在调用doBegin之后又调用了prepareSynchronization方法
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
这个方法会调用initSynchronization初始化一个ThreadLocal变量synchronizations
在初始化之前会检查该变量是否已经初始化了,如果出现就报错。
而CC的doBegin是调用了getTransaction,所以该变量会初始化多次,所以导致无法通过检查。
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
if (status.isNewSynchronization()) {
TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
(definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) ?
definition.getIsolationLevel() : null);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
TransactionSynchronizationManager.initSynchronization();
}
}
但是如果我们把transactionManager 的transactionSynchronization设置为SYNCHRONIZATION_NEVER,就会避免initSynchronization重复初始化问题,
因为MultipleDataSourcesTransactionManager的isNewSynchronization属性为false,initSynchronization就不会执行。
[b][size=large]Spring3.x中设置如下[/size][/b]:
<bean id="transactionManager" class="com.alibaba.cobar.client.transaction.MultipleDataSourcesTransactionManager">
<property name="cobarDataSourceService" ref="dataSources" />
<property name="transactionSynchronization" value="2" />
</bean>
TransactionSynchronization的含义:
下面摘自网上的描述
[i]TransactionSynchronization是可以注册到事务处理过程中的回调接口。它就像是事务处理的事件监听器,当事务处理的某些规定时点发生时,会调用TransactionSynchronization上的一些方法来执行相应的回调逻辑,如在事务完成后清理相应的系统资源等操作。Spring事务抽象框架所定义的TransactionSynchronization类似于JTA规范的javax.transaction.Synchronization,但比JTA的Synchronization提供了更多的回调方法,允许我们对事务的处理添加更多的回调逻辑。[/i]
看起来TransactionSynchronization应该是类似AOP的一种对事务事件的回调,不过我没有用过。
[size=large][b]可能导致的问题[/b][/size]:
个人分析-不会,因为我们屏蔽的只是CC的MultipleDataSourcesTransactionManager的transactionSynchronization属性,而实际的数据源事务管理器的transactionSynchronization仍然是默认的SYNCHRONIZATION_ALWAYS。
总结一下,可以这样认为,我们在CC中不支持transactionSynchronization特性。
其实我们对MultipleDataSourcesTransactionManager设置的属性都没有应用到的数据源事务管理器DataSourcesTransactionManager上
下一篇: 公孙瓒是什么实力?他为什么敢单挑吕布
推荐阅读
-
分析Python编程时利用wxPython来支持多线程的方法
-
[Abp vNext 源码分析] - 5. DDD 的领域层支持(仓储、实体、值对象)
-
Kudu:支持快速分析的新型Hadoop存储系统
-
[Abp vNext 源码分析] - 6. DDD 的应用层支持 (应用服务)
-
购买GoDaddy主机不支持支付宝付款的原因分析
-
分析Python编程时利用wxPython来支持多线程的方法
-
分析机构看好明年支持5G的iPhone 12:出货量相当于华为/三星之和
-
Vscode中不再支持JDK8的原因分析及解决方案
-
win2003 iis 不支持请求(iis iso)的解决方法分析
-
基于Flink流处理的动态实时亿级用户全端数据统计分析系统(支持所有的终端统计) flink