/**
* 这个类实现了ImportBeanDefinitionRegistrar,他在启动的时候会调用registerBeanDefinitions方法。
* 最核心的逻辑是往Spring容器中注册了一个InfrastructureAdvisorAutoProxyCreator的Bean。
* InfrastructureAdvisorAutoProxyCreator继承了AbstractAdvisorAutoProxyCreator,所以这个类的主要作用就是开启自动代理的作用,也就是一个BeanPostProcessor,会在初始化后步骤中去寻找Advisor类型的Bean,并判断当前某个Bean是否有匹配的Advisor,是否需要利用动态代理产生一个代理对象。
*/publicclassAutoProxyRegistrarimplementsImportBeanDefinitionRegistrar{publicvoidregisterBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){boolean candidateFound =false;
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();for(String annType : annTypes){
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);if(candidate == null){continue;}
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");if(mode != null && proxyTargetClass != null && AdviceMode.class== mode.getClass()&&
Boolean.class== proxyTargetClass.getClass()){
candidateFound =true;if(mode == AdviceMode.PROXY){// 注册InfrastructureAdvisorAutoProxyCreator,才可以Bean进行AOP
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);if((Boolean) proxyTargetClass){// 设置InfrastructureAdvisorAutoProxyCreator的proxyTargetClass为true
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);return;}}}}if(!candidateFound && logger.isInfoEnabled()){
String name =getClass().getSimpleName();
logger.info(String.format("%s was imported but no annotations were found "+"having both 'mode' and 'proxyTargetClass' attributes of type "+"AdviceMode and boolean respectively. This means that auto proxy "+"creator registration and configuration may not have occurred as "+"intended, and components may not be proxied as expected. Check to "+"ensure that %s has been @Import'ed on the same class where these "+"annotations are declared; otherwise remove the import of %s "+"altogether.", name, name, name));}}}
/**
* 之前存在事务的执行逻辑
* 源码位置:org.springframework.transaction.support.AbstractPlatformTransactionManager.handleExistingTransaction(TransactionDefinition, Object, boolean)
*/private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction,boolean debugEnabled)throws TransactionException {// PROPAGATION_NEVER:以非事务方式进行,如果存在事务则抛出异常if(definition.getPropagationBehavior()== TransactionDefinition.PROPAGATION_NEVER){thrownewIllegalTransactionStateException("Existing transaction found for transaction marked with propagation 'never'");}// PROPAGATION_NOT_SUPPORTED:以非事务方式执行,如果当前存在事务则将当前事务挂起if(definition.getPropagationBehavior()== TransactionDefinition.PROPAGATION_NOT_SUPPORTED){if(debugEnabled){
logger.debug("Suspending current transaction");}// 把当前事务挂起,其中就会把数据库连接对象从ThreadLocal中移除
Object suspendedResources =suspend(transaction);boolean newSynchronization =(getTransactionSynchronization()== SYNCHRONIZATION_ALWAYS);returnprepareTransactionStatus(
definition, null,false, newSynchronization, debugEnabled, suspendedResources);}// PROPAGATION_REQUIRES_NEW:创建一个新的事务并挂起当前事务if(definition.getPropagationBehavior()== TransactionDefinition.PROPAGATION_REQUIRES_NEW){if(debugEnabled){
logger.debug("Suspending current transaction, creating new transaction with name ["+
definition.getName()+"]");}// 调用挂起的逻辑
SuspendedResourcesHolder suspendedResources =suspend(transaction);// 开启新事务的逻辑try{returnstartTransaction(definition, transaction, debugEnabled, suspendedResources);}catch(RuntimeException| Error beginEx){resumeAfterBeginException(transaction, suspendedResources, beginEx);throw beginEx;}}// PROPAGATION_NESTED:果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则创建一个事务。if(definition.getPropagationBehavior()== TransactionDefinition.PROPAGATION_NESTED){if(!isNestedTransactionAllowed()){thrownewNestedTransactionNotSupportedException("Transaction manager does not allow nested transactions by default - "+"specify 'nestedTransactionAllowed' property with value 'true'");}if(debugEnabled){
logger.debug("Creating nested transaction with name ["+ definition.getName()+"]");}if(useSavepointForNestedTransaction()){// Create savepoint within existing Spring-managed transaction,// through the SavepointManager API implemented by TransactionStatus.// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
DefaultTransactionStatus status =prepareTransactionStatus(definition, transaction,false,false, debugEnabled, null);// 创建一个savepoint
status.createAndHoldSavepoint();return status;}else{// Nested transaction through nested begin and commit/rollback calls.// Usually only for JTA: Spring synchronization might get activated here// in case of a pre-existing JTA transaction.returnstartTransaction(definition, transaction, debugEnabled, null);}}// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.if(debugEnabled){
logger.debug("Participating in existing transaction");}if(isValidateExistingTransaction()){if(definition.getIsolationLevel()!= TransactionDefinition.ISOLATION_DEFAULT){
Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();if(currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()){
Constants isoConstants = DefaultTransactionDefinition.constants;thrownewIllegalTransactionStateException("Participating transaction with definition ["+
definition +"] specifies isolation level which is incompatible with existing transaction: "+(currentIsolationLevel != null ?
isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION):"(unknown)"));}}if(!definition.isReadOnly()){if(TransactionSynchronizationManager.isCurrentTransactionReadOnly()){thrownewIllegalTransactionStateException("Participating transaction with definition ["+
definition +"] is not marked as read-only but existing transaction is");}}}// 如果依然是Propagation.REQUIREDboolean newSynchronization =(getTransactionSynchronization()!= SYNCHRONIZATION_NEVER);returnprepareTransactionStatus(definition, transaction,false, newSynchronization, debugEnabled, null);}
事务的提交逻辑
/**
* 事务的提交
*/protectedvoidcommitTransactionAfterReturning(@Nullable TransactionInfo txInfo){if(txInfo != null && txInfo.getTransactionStatus()!= null){if(logger.isTraceEnabled()){
logger.trace("Completing transaction for ["+ txInfo.getJoinpointIdentification()+"]");}
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());}}/**
* 事务提交的准备逻辑
*/publicfinalvoidcommit(TransactionStatus status)throws TransactionException {if(status.isCompleted()){thrownewIllegalTransactionStateException("Transaction is already completed - do not call commit or rollback more than once per transaction");}
DefaultTransactionStatus defStatus =(DefaultTransactionStatus) status;// 可以通过TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();来设置// 事务本来是可以要提交的,但是可以强制回滚。比如报错后更有好的提示。if(defStatus.isLocalRollbackOnly()){if(defStatus.isDebug()){
logger.debug("Transactional code has requested rollback");}processRollback(defStatus,false);return;}// 判断此事务在之前是否设置了需要回滚,跟globalRollbackOnParticipationFailure有关if(!shouldCommitOnGlobalRollbackOnly()&& defStatus.isGlobalRollbackOnly()){if(defStatus.isDebug()){
logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");}processRollback(defStatus,true);return;}// 提交processCommit(defStatus);}/**
* 提交外部逻辑
*/privatevoidprocessCommit(DefaultTransactionStatus status)throws TransactionException {try{boolean beforeCompletionInvoked =false;try{boolean unexpectedRollback =false;// 空方法,无任何子类的实现prepareForCommit(status);// 调用同步器提交前的逻辑(回滚的时候不调用这个)triggerBeforeCommit(status);// 调用同步器完成前的逻辑triggerBeforeCompletion(status);
beforeCompletionInvoked =true;if(status.hasSavepoint()){if(status.isDebug()){
logger.debug("Releasing transaction savepoint");}
unexpectedRollback = status.isGlobalRollbackOnly();
status.releaseHeldSavepoint();}// 新的事务,直接调用提交elseif(status.isNewTransaction()){if(status.isDebug()){
logger.debug("Initiating transaction commit");}
unexpectedRollback = status.isGlobalRollbackOnly();// 调用提交方法doCommit(status);}elseif(isFailEarlyOnGlobalRollbackOnly()){
unexpectedRollback = status.isGlobalRollbackOnly();}// Throw UnexpectedRollbackException if we have a global rollback-only// marker but still didn't get a corresponding exception from commit.if(unexpectedRollback){thrownewUnexpectedRollbackException("Transaction silently rolled back because it has been marked as rollback-only");}}catch(UnexpectedRollbackException ex){// can only be caused by doCommittriggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);throw ex;}catch(TransactionException ex){// can only be caused by doCommitif(isRollbackOnCommitFailure()){doRollbackOnCommitException(status, ex);}else{triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);}throw ex;}catch(RuntimeException| Error ex){if(!beforeCompletionInvoked){triggerBeforeCompletion(status);}doRollbackOnCommitException(status, ex);throw ex;}// Trigger afterCommit callbacks, with an exception thrown there// propagated to callers but the transaction still considered as committed.try{// 调用同步器提交后的逻辑triggerAfterCommit(status);}finally{// 调用同步器完成后的逻辑triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);}}finally{// 恢复被挂起的资源到当前线程中cleanupAfterCompletion(status);}}/**
* 提交的核心逻辑,直接调用Connection的提交方法
*/protectedvoiddoCommit(DefaultTransactionStatus status){
DataSourceTransactionObject txObject =(DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();if(status.isDebug()){
logger.debug("Committing JDBC transaction on Connection ["+ con +"]");}try{
con.commit();}catch(SQLException ex){throwtranslateException("JDBC commit", ex);}}/**
* 恢复被挂起的资源到当前线程中
*/privatevoidcleanupAfterCompletion(DefaultTransactionStatus status){
status.setCompleted();if(status.isNewSynchronization()){
TransactionSynchronizationManager.clear();}// 判断当前事务执行的方法,是不是创建这个事务的方法if(status.isNewTransaction()){// 这里会去关闭数据库连接doCleanupAfterCompletion(status.getTransaction());}// 恢复被挂起的资源到当前线程中if(status.getSuspendedResources()!= null){if(status.isDebug()){
logger.debug("Resuming suspended transaction after completion of inner transaction");}
Object transaction =(status.hasTransaction()? status.getTransaction(): null);// 恢复resume(transaction,(SuspendedResourcesHolder) status.getSuspendedResources());}}
回滚事务的逻辑
protectedvoidcompleteTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex){if(txInfo != null && txInfo.getTransactionStatus()!= null){if(logger.isTraceEnabled()){
logger.trace("Completing transaction for ["+ txInfo.getJoinpointIdentification()+"] after exception: "+ ex);}// transactionAttribute的实现类为RuleBasedTransactionAttribute,父类为DefaultTransactionAttribute// 判断配置的rollBackFor的异常信息if(txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)){try{
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());}catch(TransactionSystemException ex2){
logger.error("Application exception overridden by rollback exception", ex);
ex2.initApplicationException(ex);throw ex2;}catch(RuntimeException| Error ex2){
logger.error("Application exception overridden by rollback exception", ex);throw ex2;}}else{// We don't roll back on this exception.// Will still roll back if TransactionStatus.isRollbackOnly() is true.try{
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());}catch(TransactionSystemException ex2){
logger.error("Application exception overridden by commit exception", ex);
ex2.initApplicationException(ex);throw ex2;}catch(RuntimeException| Error ex2){
logger.error("Application exception overridden by commit exception", ex);throw ex2;}}}}/**
* 判断回滚条件是否满足
* 源码位置:org.springframework.transaction.interceptor.RuleBasedTransactionAttribute.rollbackOn(Throwable)
*/publicbooleanrollbackOn(Throwable ex){
RollbackRuleAttribute winner = null;int deepest = Integer.MAX_VALUE;if(this.rollbackRules != null){// 遍历所有的RollbackRuleAttribute,判断现在抛出的异常ex是否匹配RollbackRuleAttribute中指定的异常类型的子类或本身for(RollbackRuleAttribute rule :this.rollbackRules){int depth = rule.getDepth(ex);if(depth >=0&& depth < deepest){
deepest = depth;
winner = rule;}}}// User superclass behavior (rollback on unchecked) if no rule matches.// 没有匹配的规则,调用父类判断是不是运行时异常if(winner == null){returnsuper.rollbackOn(ex);}// ex所匹配的RollbackRuleAttribute,可能是NoRollbackRuleAttribute,如果是匹配的NoRollbackRuleAttribute,那就表示现在这个异常ex不用回滚return!(winner instanceofNoRollbackRuleAttribute);}/**
* 回滚前的准备逻辑
* 源码位置:org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(TransactionStatus)
*/publicfinalvoidrollback(TransactionStatus status)throws TransactionException {// 不完整的,没有执行完抛异常if(status.isCompleted()){thrownewIllegalTransactionStateException("Transaction is already completed - do not call commit or rollback more than once per transaction");}
DefaultTransactionStatus defStatus =(DefaultTransactionStatus) status;processRollback(defStatus,false);}/**
* 回滚
*/privatevoidprocessRollback(DefaultTransactionStatus status,boolean unexpected){try{boolean unexpectedRollback = unexpected;try{// 只会触发完成前的同步器逻辑triggerBeforeCompletion(status);// 比如mysql中的savepointif(status.hasSavepoint()){if(status.isDebug()){
logger.debug("Rolling back transaction to savepoint");}// 回滚到上一个savepoint位置
status.rollbackToHeldSavepoint();}elseif(status.isNewTransaction()){if(status.isDebug()){
logger.debug("Initiating transaction rollback");}// 如果当前执行的方法是新开了一个事务,那么就直接回滚doRollback(status);}else{// Participating in larger transaction// 如果当前执行的方法,是公用了一个已存在的事务,而当前执行的方法抛了异常,则要判断整个事务到底要不要回滚,看具体配置if(status.hasTransaction()){// 如果一个事务中有两个方法,第二个方法抛异常了,那么第二个方法就相当于执行失败需要回滚,如果globalRollbackOnParticipationFailure为true,那么第一个方法在没有抛异常的情况下也要回滚if(status.isLocalRollbackOnly()||isGlobalRollbackOnParticipationFailure()){if(status.isDebug()){
logger.debug("Participating transaction failed - marking existing transaction as rollback-only");}// 直接将rollbackOnly设置到ConnectionHolder中去,表示整个事务的sql都要回滚doSetRollbackOnly(status);}else{if(status.isDebug()){
logger.debug("Participating transaction failed - letting transaction originator decide on rollback");}}}else{
logger.debug("Should roll back transaction but cannot - no transaction available");}// Unexpected rollback only matters here if we're asked to fail earlyif(!isFailEarlyOnGlobalRollbackOnly()){
unexpectedRollback =false;}}}catch(RuntimeException| Error ex){triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);throw ex;}triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);// Raise UnexpectedRollbackException if we had a global rollback-only markerif(unexpectedRollback){thrownewUnexpectedRollbackException("Transaction rolled back because it has been marked as rollback-only");}}finally{cleanupAfterCompletion(status);}}