敞开生长之旅!这是我参加「日新计划 12 月更文挑战」的第14天,点击检查活动详情
前言
java
程序员都基本上会使用spring
,在对数据库进行操作时,常常涉及到业务的处理,spring
业务的完成是基于数据库自身的业务,可是spring
业务在数据库业务的基础上做了必定的增强,比方7大传达特性的完成能够帮助开发人员在杂乱的业务需求中灵活地应对,那么这7大传达特性是怎么完成的呢?
源码解析
关于上面的问题,咱们能够定位到AbstractPlatformTransactionManager.getTransaction()
办法:
publicfinalTransactionStatusgetTransaction(@NullableTransactionDefinitiondefinition)throwsTransactionException{
// 获取业务定义,其实便是咱们写代码的时候加上的@Transactional解析得到的TransactionDefinition
TransactionDefinitiondef=definition!=null?definition:TransactionDefinition.withDefaults();
// 获取当时的业务,其实便是从ThreadLocal中获取当时线程是否正在其他业务当中
Objecttransaction=this.doGetTransaction();
booleandebugEnabled=this.logger.isDebugEnabled();
// 假如当时存在业务
if(this.isExistingTransaction(transaction)) {
// 依据传达特性来处理,后面会解说;handleExistingTransaction办法处理的都是在现已存在业务的情况下的业务逻辑
returnthis.handleExistingTransaction(def,transaction,debugEnabled);
}elseif(def.getTimeout()<-1) {
thrownewInvalidTimeoutException("Invalid transaction timeout",def.getTimeout());
}elseif(def.getPropagationBehavior()==2) {
// 假如传达特性设置的是PROPAGATION_MANDATORY,2代表PROPAGATION_MANDATORY,假如当时没有业务,那么抛反常
thrownewIllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'");
}elseif(def.getPropagationBehavior()!=0&&def.getPropagationBehavior()!=3&&def.getPropagationBehavior()!=6) {
// 假如传达特性不为0,3,6;其实就表明假如传达特性为1或4或5;也便是PROPAGATION_SUPPORTS或PROPAGATION_NOT_SUPPORTED或PROPAGATION_NEVER,以非业务状况履行
if(def.getIsolationLevel()!=-1&&this.logger.isWarnEnabled()) {
this.logger.warn("Custom isolation level specified but no actual transaction initiated; isolation level will effectively be ignored: "+def);
}
booleannewSynchronization=this.getTransactionSynchronization()==0;
returnthis.prepareTransactionStatus(def, (Object)null,true,newSynchronization,debugEnabled, (Object)null);
}else{
// 剩下的情况便是传达特性为0或3或6,也便是PROPAGATION_REQUIRED或PROPAGATION_REQUIRES_NEW或PROPAGATION_NESTED,那么就敞开新业务履行
AbstractPlatformTransactionManager.SuspendedResourcesHoldersuspendedResources=this.suspend((Object)null);
if(debugEnabled) {
this.logger.debug("Creating new transaction with name ["+def.getName()+"]: "+def);
}
try{
returnthis.startTransaction(def,transaction,debugEnabled,suspendedResources);
}catch(Error|RuntimeExceptionvar7) {
this.resume((Object)null,suspendedResources);
throwvar7;
}
}
}
在上述源码中,咱们主要重视假如当时不存在业务的前提下,spring
是怎么处理的:
1.当时存在业务,交给
handleExistingTransaction()
处理,后续解说;下面都是当时没有业务的情况下:
2.在没有业务的情况下,假如设置的传达特性是
PROPAGATION_MANDATORY
,那么抛反常;所以PROPAGATION_MANDATORY
是要求当时必须存在业务的;3.在没有业务的情况下,假如设置的传达特性是[
PROPAGATION_SUPPORTS
,PROPAGATION_NOT_SUPPORTED
,PROPAGATION_NEVER
]之一,那么都以非业务状况履行;4.在没有业务的情况下,假如设置的传达特性是[
PROPAGATION_REQUIRED
,PROPAGATION_REQUIRES_NEW
,PROPAGATION_NESTED
]之一,那么将敞开新业务履行;
下面咱们来看一下handleExistingTransaction()
是怎么处理有业务的情况的:
privateTransactionStatushandleExistingTransaction(TransactionDefinitiondefinition,Objecttransaction,booleandebugEnabled)throwsTransactionException{
// 在有业务的情况下,假如当时传达特性设置的是PROPAGATION_NEVER,那么直接抛反常;
if(definition.getPropagationBehavior()==5) {
thrownewIllegalTransactionStateException("Existing transaction found for transaction marked with propagation 'never'");
}else{
AbstractPlatformTransactionManager.SuspendedResourcesHoldersuspendedResources;
// 在有业务的情况下,假如传达特性是PROPAGATION_NOT_SUPPORTED,那么以非业务状况履行;
if(definition.getPropagationBehavior()==4) {
if(debugEnabled) {
this.logger.debug("Suspending current transaction");
}
suspendedResources=this.suspend(transaction);
booleannewSynchronization=this.getTransactionSynchronization()==0;
returnthis.prepareTransactionStatus(definition, (Object)null,false,newSynchronization,debugEnabled,suspendedResources);
}elseif(definition.getPropagationBehavior()==3) {
// 在有业务的情况下,假如传达特性是PROPAGATION_REQUIRES_NEW,那么将敞开新业务履行;
if(debugEnabled) {
this.logger.debug("Suspending current transaction, creating new transaction with name ["+definition.getName()+"]");
}
suspendedResources=this.suspend(transaction);
try{
returnthis.startTransaction(definition,transaction,debugEnabled,suspendedResources);
}catch(Error|RuntimeExceptionvar6) {
this.resumeAfterBeginException(transaction,suspendedResources,var6);
throwvar6;
}
}elseif(definition.getPropagationBehavior()==6) {
// 在有业务的情况下,假如传达特性是PROPAGATION_NESTED而且答应嵌套业务的情况下,将敞开新业务履行,否则将抛反常
if(!this.isNestedTransactionAllowed()) {
thrownewNestedTransactionNotSupportedException("Transaction manager does not allow nested transactions by default - specify 'nestedTransactionAllowed' property with value 'true'");
}else{
if(debugEnabled) {
this.logger.debug("Creating nested transaction with name ["+definition.getName()+"]");
}
if(this.useSavepointForNestedTransaction()) {
DefaultTransactionStatusstatus=this.prepareTransactionStatus(definition,transaction,false,false,debugEnabled, (Object)null);
status.createAndHoldSavepoint();
returnstatus;
}else{
returnthis.startTransaction(definition,transaction,debugEnabled, (AbstractPlatformTransactionManager.SuspendedResourcesHolder)null);
}
}
}else{
// 在有业务的情况下,假如传达特性为PROPAGATION_REQUIRED或PROPAGATION_SUPPORTS或PROPAGATION_MANDATORY,那么直接使用当时业务履行;
if(debugEnabled) {
this.logger.debug("Participating in existing transaction");
}
if(this.isValidateExistingTransaction()) {
if(definition.getIsolationLevel()!=-1) {
IntegercurrentIsolationLevel=TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
if(currentIsolationLevel==null||currentIsolationLevel!=definition.getIsolationLevel()) {
ConstantsisoConstants=DefaultTransactionDefinition.constants;
thrownewIllegalTransactionStateException("Participating transaction with definition ["+definition+"] specifies isolation level which is incompatible with existing transaction: "+(currentIsolationLevel!=null?isoConstants.toCode(currentIsolationLevel,"ISOLATION_") :"(unknown)"));
}
}
if(!definition.isReadOnly()&&TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
thrownewIllegalTransactionStateException("Participating transaction with definition ["+definition+"] is not marked as read-only but existing transaction is");
}
}
booleannewSynchronization=this.getTransactionSynchronization()!=2;
returnthis.prepareTransactionStatus(definition,transaction,false,newSynchronization,debugEnabled, (Object)null);
}
}
}
通过上述源码分析,咱们很清楚地知道了在有业务的情况下,业务的传达特性是怎么处理的:
1.在有业务的情况下,假如当时传达特性设置的是PROPAGATION_NEVER,那么直接抛反常;
2.在有业务的情况下,假如传达特性是PROPAGATION_NOT_SUPPORTED,那么挂起当时业务,并以非业务状况履行业务逻辑;
3.在有业务的情况下,假如传达特性是PROPAGATION_REQUIRES_NEW,那么挂起当时业务,并将敞开新业务履行;
4.在有业务的情况下,假如传达特性是PROPAGATION_NESTED而且答应嵌套业务的情况下,将敞开新业务履行,否则将抛反常
5.在有业务的情况下,假如传达特性为PROPAGATION_REQUIRED或PROPAGATION_SUPPORTS或PROPAGATION_MANDATORY,那么直接使用当时业务履行;