Spring事务

Spring事务使用

我们以JdbcTemplate为例,其他orm框架也是一样的原理

配置类

@EnableTransactionManagement
@Configuration
@ComponentScan("com.yoocar.spring")
public class SpringConfig {

    private String username="root";

    private String password="lusaisai720633";

    private String driver="com.mysql.jdbc.Driver";

    private String url="jdbc:mysql://47.116.142.177:3306/springbootexample?characterEncoding=utf8";


    //数据源
   @Bean
   public DataSource dataSource(){
        DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
        driverManagerDataSource.setDriverClassName(driver);
        driverManagerDataSource.setUrl(url);
        driverManagerDataSource.setUsername(username);
        driverManagerDataSource.setPassword(password);
        return driverManagerDataSource;
    }

    //jdbcTemplate
    @Bean
    public JdbcTemplate jdbcTemplate(){
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
        return jdbcTemplate;
    }

    //事务管理器
    @Bean
    public PlatformTransactionManager transactionManager(){
	    return new DataSourceTransactionManager(dataSource());
    }


}

service

@Component
public class UserJdbcService {


    private JdbcTemplate jdbcTemplate;

    @Autowired
    public UserJdbcService(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    /**
     * 执行 INSERT
     */
    @Transactional(rollbackFor = RuntimeException.class,propagation = Propagation.REQUIRED)
    public void testInsert() {
        String sql = "INSERT INTO xwj_user(id, last_name, age) VALUES(?, ?, ?)";
        jdbcTemplate.update(sql, "1", "a-xwj", 0);
        //throw new NullPointerException();
    }

}

启动类

public static void main(String[] args) {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
    UserJdbcService userJdbcService = (UserJdbcService) applicationContext.getBean("userJdbcService");
    userJdbcService.testInsert();

}

Spring事务传播机制

其中,以非事务方式运行,表示以非Spring事务运行,表示在执行这个方法时,Spring事务管理器不会去建立数据库连接,执行sql时,由Mybatis或JdbcTemplate自己来建立数据库连接来执行sql。

传播机制分类

  • PROPAGATION_REQUIRED 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。
  • PROPAGATION_SUPPORTS 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。
  • PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。需手动开启事务
  • PROPAGATION_REQUIRES_NEW 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
  • PROPAGATION_NOT_SUPPORTED 总是非事务地执行,并挂起任何存在的事务。
  • PROPAGATION_NEVER 总是非事务地执行,如果存在一个活动事务,则抛出异常
  • PROPAGATION_NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则开启一个新的事务。

情况1

@Component
public class UserService {
	@Autowired
	private UserService userService;

	@Transactional
	public void test() {
		// test方法中的sql
		userService.a();
	}

	@Transactional
	public void a() {
		// a方法中的sql
	}
}

默认情况下传播机制为REQUIRED,表示当前如果没有事务则新建一个事务,如果有事务则在当前事务中执行。****

所以上面这种情况的执行流程如下:

  1. 新建一个数据库连接conn
  2. 设置conn的autocommit为false
  3. 执行test方法中的sql
  4. 执行a方法中的sql
  5. 执行conn的commit()方法进行提交

因此,这里是一个数据库连接,一个事务

情况2

假如是这种情况

@Component
public class UserService {
	@Autowired
	private UserService userService;

	@Transactional
	public void test() {
		// test方法中的sql
		userService.a();
        int result = 100/0;
	}

	@Transactional
	public void a() {
		// a方法中的sql
	}
}

所以上面这种情况的执行流程如下:

  1. 新建一个数据库连接conn
  2. 设置conn的autocommit为false
  3. 执行test方法中的sql
  4. 执行a方法中的sql
  5. 抛出异常
  6. 执行conn的rollback()方法进行回滚,所以两个方法中的sql都会回滚掉

因此,这里是一个数据库连接,一个事务

情况3

假如是这种情况:

@Component
public class UserService {
	@Autowired
	private UserService userService;

	@Transactional
	public void test() {
		// test方法中的sql
		userService.a();
	}

	@Transactional
	public void a() {
		// a方法中的sql
        int result = 100/0;
	}
}

所以上面这种情况的执行流程如下:

  1. 新建一个数据库连接conn
  2. 设置conn的autocommit为false
  3. 执行test方法中的sql
  4. 执行a方法中的sql
  5. 抛出异常
  6. 执行conn的rollback()方法进行回滚,所以两个方法中的sql都会回滚掉

因此,这里是一个数据库连接,一个事务

情况4

如果是这种情况:

@Component
public class UserService {
	@Autowired
	private UserService userService;

	@Transactional
	public void test() {
		// test方法中的sql
		userService.a();
	}

	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void a() {
		// a方法中的sql
		int result = 100/0;
	}
}

所以上面这种情况的执行流程如下:

  1. 新建一个数据库连接conn
  2. 设置conn的autocommit为false
  3. 执行test方法中的sql
  4. 又新建一个数据库连接conn2
  5. 执行a方法中的sql
  6. 抛出异常
  7. 执行conn2的rollback()方法进行回滚
  8. 继续抛异常,对于test()方法而言,它会接收到一个异常,然后抛出
  9. 执行conn的rollback()方法进行回滚,最终还是两个方法中的sql都回滚了

因此,这里是2个数据库连接,2个事务,但最后都回滚了

情况5

如果是这种情况:

@Component
public class UserService {
	@Autowired
	private UserService userService;

	@Transactional
	public void test() {
		// test方法中的sql
		try {
           userService.a();
        } catch (Exception e) {
            e.printStackTrace();
        }
	}

	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void a() {
		// a方法中的sql
		int result = 100/0;
	}
}

所以上面这种情况的执行流程如下:

  1. 新建一个数据库连接conn
  2. 设置conn的autocommit为false
  3. 执行test方法中的sql
  4. 又新建一个数据库连接conn2
  5. 执行a方法中的sql
  6. 抛出异常
  7. 执行conn2的rollback()方法进行回滚
  8. 继续抛异常,对于test()方法而言,它会接收到一个异常,然后捕获处理,这里conn没有异常
  9. 执行conn的commit方法,最终a()方法中的sql回滚了,test方法的sql执行了

因此,这里是2个数据库连接,2个事务,但最终a()方法中的sql回滚了,test方法的sql执行了

Spring事务强制回滚

正常情况下,a()调用b()方法时,如果b()方法抛了异常,但是在a()方法捕获了,那么a()的事务还是会正常提交的,但是有的时候,我们捕获异常可能仅仅只是不把异常信息返回给客户端,而是为了返回一些更友好的错误信息,而这个时候,我们还是希望事务能回滚的,那这个时候就得告诉Spring把当前事务回滚掉,做法就是:

@Transactional
public void test(){
	
    // 执行sql
	try {
		b();
	} catch (Exception e) {
		// 构造友好的错误信息返回
		TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
	}
    
}

public void b() throws Exception {
	throw new Exception();
}

TransactionSynchronization

Spring事务有可能会提交,回滚、挂起、恢复,所以Spring事务提供了一种机制,可以让程序员来监听当前Spring事务所处于的状态。

@Component
public class UserService {

	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Autowired
	private UserService userService;

	@Transactional
	public void test(){
		TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {

			@Override
			public void suspend() {
				System.out.println("test被挂起了");
			}

			@Override
			public void resume() {
				System.out.println("test被恢复了");
			}

			@Override
			public void beforeCommit(boolean readOnly) {
				System.out.println("test准备要提交了");
			}

			@Override
			public void beforeCompletion() {
				System.out.println("test准备要提交或回滚了");
			}

			@Override
			public void afterCommit() {
				System.out.println("test提交成功了");
			}

			@Override
			public void afterCompletion(int status) {
				System.out.println("test提交或回滚成功了");
			}
		});

		jdbcTemplate.execute("insert into t1 values(1,1,1,1,'1')");
		System.out.println("test");
		userService.a();
	}

	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void a(){
		TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {

			@Override
			public void suspend() {
				System.out.println("a被挂起了");
			}

			@Override
			public void resume() {
				System.out.println("a被恢复了");
			}

			@Override
			public void beforeCommit(boolean readOnly) {
				System.out.println("a准备要提交了");
			}

			@Override
			public void beforeCompletion() {
				System.out.println("a准备要提交或回滚了");
			}

			@Override
			public void afterCommit() {
				System.out.println("a提交成功了");
			}

			@Override
			public void afterCompletion(int status) {
				System.out.println("a提交或回滚成功了");
			}
		});

		jdbcTemplate.execute("insert into t1 values(2,2,2,2,'2')");
		System.out.println("a");
	}


}

Spring事务源码分析

@EnableTransactionManagement

开启Spring事务本质上就是注册了一个TransactionManagementConfigurationSelector

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

   boolean proxyTargetClass() default false;


   AdviceMode mode() default AdviceMode.PROXY;


   int order() default Ordered.LOWEST_PRECEDENCE;

}

TransactionManagementConfigurationSelector源码

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

   
   @Override
   protected String[] selectImports(AdviceMode adviceMode) {
      switch (adviceMode) {
      	//一般就是PROXY
         case PROXY:
         	//向Spring容器中添加了两个Bean
            return new String[] {AutoProxyRegistrar.class.getName(),
                  ProxyTransactionManagementConfiguration.class.getName()};
         case ASPECTJ:
            return new String[] {determineTransactionAspectClass()};
         default:
            return null;
      }
   }

   private String determineTransactionAspectClass() {
      return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
            TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
            TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
   }

}

开启Spring事务的注解本质上就是增加了一个Advisor

可以看到我们使用@EnableTransactionManagement注解来开启Spring事务是,该注解就是向Spring容器中添加了两个Bean:

  1. AutoProxyRegistrar
  2. ProxyTransactionManagementConfiguration

AutoProxyRegistrar

AutoProxyRegistrar实现了ImportBeanDefinitionRegistrar,核心的逻辑在于其方法registerBeanDefinitions

源码如下

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

   private final Log logger = LogFactory.getLog(getClass());

   @Override
   public void registerBeanDefinitions(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) {
            //在这里注册了一个Advisor的bean
               AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
               if ((Boolean) proxyTargetClass) {
                  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));
      }
   }

}

跟 AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);

@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
   return registerAutoProxyCreatorIfNecessary(registry, null);
}

@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
      BeanDefinitionRegistry registry, @Nullable Object source) {

   return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

可以看到,AutoProxyRegistrar主要的作用是向Spring容器中注册了一个InfrastructureAdvisorAutoProxyCreator的Bean。

而InfrastructureAdvisorAutoProxyCreator继承了AbstractAdvisorAutoProxyCreator

所以这个类的主要作用就是开启自动代理的作用,也就是一个BeanPostProcessor,会在初始化后步骤中去寻找Advisor类型的Bean,并判断当前某个Bean是否有匹配的Advisor,是否需要利用动态代理产生一个代理对象。类结构如下

image

接下来看下添加的第二个Bean

ProxyTransactionManagementConfiguration

它是一个配置类,它又定义了另外三个bean:

  1. BeanFactoryTransactionAttributeSourceAdvisor:一个Advisor
  2. AnnotationTransactionAttributeSource:相当于BeanFactoryTransactionAttributeSourceAdvisor中的Pointcut
  3. TransactionInterceptor:相当于BeanFactoryTransactionAttributeSourceAdvisor中的Advice

源码如下

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

//添加一个BeanFactoryTransactionAttributeSourceAdvisor
   @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
         TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {

      BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
      advisor.setTransactionAttributeSource(transactionAttributeSource);
      advisor.setAdvice(transactionInterceptor);
      if (this.enableTx != null) {
         advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
      }
      return advisor;
   }

//添加一个AnnotationTransactionAttributeSource,相当于BeanFactoryTransactionAttributeSourceAdvisor中的Pointcut
   @Bean
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public TransactionAttributeSource transactionAttributeSource() {
      return new AnnotationTransactionAttributeSource();
   }

//添加一个TransactionInterceptor:相当于BeanFactoryTransactionAttributeSourceAdvisor中的Advice
   @Bean
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
      TransactionInterceptor interceptor = new TransactionInterceptor();
      interceptor.setTransactionAttributeSource(transactionAttributeSource);
      if (this.txManager != null) {
         interceptor.setTransactionManager(this.txManager);
      }
      return interceptor;
   }

}
BeanFactoryTransactionAttributeSourceAdvisor

它就是一个Advisor,简单来说Advisor=Pointcut+Advice ,详见aop一文

AnnotationTransactionAttributeSource

它就是用来判断某个类上是否存在@Transactional注解,或者判断某个方法上是否存在@Transactional注解的。

源码如下

public AnnotationTransactionAttributeSource() {
   this(true);
}

public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
   this.publicMethodsOnly = publicMethodsOnly;
   if (jta12Present || ejb3Present) {
      this.annotationParsers = new LinkedHashSet<>(4);
      //看下SpringTransactionAnnotationParser
      this.annotationParsers.add(new SpringTransactionAnnotationParser());
      if (jta12Present) {
         this.annotationParsers.add(new JtaTransactionAnnotationParser());
      }
      if (ejb3Present) {
         this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
      }
   }
   else {
      this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
   }
}

跟看下SpringTransactionAnnotationParser

public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {

//判断某个方法上是否存在@Transactional
   @Override
   public boolean isCandidateClass(Class<?> targetClass) {
      return AnnotationUtils.isCandidateClass(targetClass, Transactional.class);
   }

   @Override
   @Nullable
   public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
      AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
            element, Transactional.class, false, false);
      if (attributes != null) {
         return parseTransactionAnnotation(attributes);
      }
      else {
         return null;
      }
   }

   public TransactionAttribute parseTransactionAnnotation(Transactional ann) {
      return parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, false, false));
   }

   protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
      RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
	//解析@Transactional上的详细参数
      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"));
      rbta.setQualifier(attributes.getString("value"));

      List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
      for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
         rollbackRules.add(new RollbackRuleAttribute(rbRule));
      }
      for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
         rollbackRules.add(new RollbackRuleAttribute(rbRule));
      }
      for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
         rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
      }
      for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
         rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
      }
      rbta.setRollbackRules(rollbackRules);

      return rbta;
   }


   @Override
   public boolean equals(@Nullable Object other) {
      return (this == other || other instanceof SpringTransactionAnnotationParser);
   }

   @Override
   public int hashCode() {
      return SpringTransactionAnnotationParser.class.hashCode();
   }

}
TransactionInterceptor

它就是代理逻辑,当某个类中存在@Transactional注解时,到时就产生一个代理对象作为Bean,代理对象在执行某个方法时,最终就会进入到TransactionInterceptor的invoke()方法。而该方法就是事务主要执行流程

Spring事务invoke()方法源码流程

@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
   // Work out the target class: may be {@code null}.
   // The TransactionAttributeSource should be passed the target class
   // as well as the method, which may be from an interface.
   Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

   // Adapt to TransactionAspectSupport's invokeWithinTransaction...
   return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}

invokeWithinTransaction

@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
		final InvocationCallback invocation) throws Throwable {

	// If the transaction attribute is null, the method is non-transactional.
	// TransactionAttribute就是@Transactional中的配置
	TransactionAttributeSource tas = getTransactionAttributeSource();
	// 获取@Transactional注解中的属性值
	final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);

	// 返回Spring容器中类型为TransactionManager的Bean对象
	final TransactionManager tm = determineTransactionManager(txAttr);

	// ReactiveTransactionManager用得少,并且它只是执行方式是响应式的,原理流程和普通的是一样的
	if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
		boolean isSuspendingFunction = KotlinDetector.isSuspendingFunction(method);
		boolean hasSuspendingFlowReturnType = isSuspendingFunction &&
				COROUTINES_FLOW_CLASS_NAME.equals(new MethodParameter(method, -1).getParameterType().getName());
		if (isSuspendingFunction && !(invocation instanceof CoroutinesInvocationCallback)) {
			throw new IllegalStateException("Coroutines invocation not supported: " + method);
		}
		CoroutinesInvocationCallback corInv = (isSuspendingFunction ? (CoroutinesInvocationCallback) invocation : null);

		ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
			Class<?> reactiveType =
					(isSuspendingFunction ? (hasSuspendingFlowReturnType ? Flux.class : Mono.class) : method.getReturnType());
			ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(reactiveType);
			if (adapter == null) {
				throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
						method.getReturnType());
			}
			return new ReactiveTransactionSupport(adapter);
		});

		InvocationCallback callback = invocation;
		if (corInv != null) {
			callback = () -> CoroutinesUtils.invokeSuspendingFunction(method, corInv.getTarget(), corInv.getArguments());
		}
		Object result = txSupport.invokeWithinTransaction(method, targetClass, callback, txAttr, (ReactiveTransactionManager) tm);
		if (corInv != null) {
			Publisher<?> pr = (Publisher<?>) result;
			return (hasSuspendingFlowReturnType ? KotlinDelegate.asFlow(pr) :
					KotlinDelegate.awaitSingleOrNull(pr, corInv.getContinuation()));
		}
		return result;
	}

	// 把tm强制转换为PlatformTransactionManager,所以我们在定义时得定义PlatformTransactionManager类型
	PlatformTransactionManager ptm = asPlatformTransactionManager(tm);

	// joinpoint的唯一标识,就是当前在执行的方法名字
	final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

	// CallbackPreferringPlatformTransactionManager表示拥有回调功能的PlatformTransactionManager,也不常用,忽略
	if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
		// Standard transaction demarcation with getTransaction and commit/rollback calls.
		// 如果有必要就创建事务,这里就涉及到事务传播机制的实现了
		// TransactionInfo表示一个逻辑事务,比如两个逻辑事务属于同一个物理事务
		TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

		Object retVal;
		try {
			// This is an around advice: Invoke the next interceptor in the chain.
			// This will normally result in a target object being invoked.
			// 执行下一个Interceptor或被代理对象中的方法,简单理解就是执行业务方法,其中就会执行sql
			retVal = invocation.proceedWithInvocation(); 
		}
		catch (Throwable ex) {
			// target invocation exception
			// 抛异常了,则回滚事务
			completeTransactionAfterThrowing(txInfo, ex);
			throw ex;
		}
		finally {
			//
			cleanupTransactionInfo(txInfo);
		}

		if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
			// Set rollback-only in case of Vavr failure matching our rollback rules...
			TransactionStatus status = txInfo.getTransactionStatus();
			if (status != null && txAttr != null) {
				retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
			}
		}

		// 提交事务
		commitTransactionAfterReturning(txInfo);
		return retVal;
	}

	else {
		Object result;
		final ThrowableHolder throwableHolder = new ThrowableHolder();

		// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
		try {
			result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
				TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
				try {
					Object retVal = invocation.proceedWithInvocation();
					if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
						// Set rollback-only in case of Vavr failure matching our rollback rules...
						retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
					}
					return retVal;
				}
				catch (Throwable ex) {
					if (txAttr.rollbackOn(ex)) {
						// A RuntimeException: will lead to a rollback.
						if (ex instanceof RuntimeException) {
							throw (RuntimeException) ex;
						}
						else {
							throw new ThrowableHolderException(ex);
						}
					}
					else {
						// A normal return value: will lead to a commit.
						throwableHolder.throwable = ex;
						return null;
					}
				}
				finally {
					cleanupTransactionInfo(txInfo);
				}
			});
		}
		catch (ThrowableHolderException ex) {
			throw ex.getCause();
		}
		catch (TransactionSystemException ex2) {
			if (throwableHolder.throwable != null) {
				logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
				ex2.initApplicationException(throwableHolder.throwable);
			}
			throw ex2;
		}
		catch (Throwable ex2) {
			if (throwableHolder.throwable != null) {
				logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
			}
			throw ex2;
		}

		// Check result state: It might indicate a Throwable to rethrow.
		if (throwableHolder.throwable != null) {
			throw throwableHolder.throwable;
		}
		return result;
	}
}

createTransactionIfNecessary

如果有必要就创建事务,这里就涉及到事务传播机制的实现了,传入事务管理器,注解和事务方法名

@SuppressWarnings("serial")
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
		@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
	//如果Transaction的name没有配置,给一个默认值
	// If no name specified, apply method identification as transaction name.
	if (txAttr != null && txAttr.getName() == null) {
		txAttr = new DelegatingTransactionAttribute(txAttr) {
			@Override
			public String getName() {
				return joinpointIdentification;
			}
		};
	}

	// 每个逻辑事务都会创建一个TransactionStatus,TransactionStatus中有一个属性代表当前逻辑事务底层的物理事务是不是新的
	TransactionStatus status = null;
	//txAttr就是Transaction注解信息
	if (txAttr != null) {
		//tm就是事务管理器
		if (tm != null) {
			//得到一个TransactionStatus对象,这里就是真正的开启事务的方法
			status = tm.getTransaction(txAttr);
		}
		else {
			if (logger.isDebugEnabled()) {
				logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
						"] because no transaction manager has been configured");
			}
		}
	}

	// 返回一个TransactionInfo对象,表示得到了一个事务,可能是新创建的一个事务,也可能是拿到的已有的事务
	return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

tm.getTransaction

这里的tm就是AbstractPlatformTransactionManager,源码如下

@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
		throws TransactionException {

	//其实就是获取Transaction注解的信息
	// Use defaults if no transaction definition given.
	TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());

	// 得到一个new DataSourceTransactionObject对象,
	// new DataSourceTransactionObject  txObject
	Object transaction = doGetTransaction();
	boolean debugEnabled = logger.isDebugEnabled();
	
	//判断是否存在事务,如果存在就挂起.,第一次肯定是不存在的,这里涉及事务的传播机制
	// transaction.getConnectionHolder().isTransactionActive()
	if (isExistingTransaction(transaction)) {
		// Existing transaction found -> check propagation behavior to find out how to behave.
		return handleExistingTransaction(def, transaction, debugEnabled);
	}
	
	//检查transaction注解里有没有配置timeout,Timeout合不合法,TransactionDefinition.TIMEOUT_DEFAULT=-1
	// Check definition settings for new transaction.
	if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
		throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
	}

	//根据不同的传播机制进行不同的处理,可先看下传播机制实例,TransactionDefinition.PROPAGATION_MANDATORY是手动开启事务的意思
	// No existing transaction found -> check propagation behavior to find out how to proceed.
	if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
		throw new IllegalTransactionStateException(
				"No existing transaction found for transaction marked with propagation 'mandatory'");
	}
	// 在当前Thread中没有事务的前提下,以下三个是等价的,TransactionDefinition.PROPAGATION_REQUIRED是默认的传播机制
	else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
			def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
			def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
		// 一般没有事务需要挂起,这里可以忽略
		SuspendedResourcesHolder suspendedResources = suspend(null);
		if (debugEnabled) {
			logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
		}
		try {
			// 开启事务后,transaction中就会有数据库连接了,并且isTransactionActive为true
			// 并返回TransactionStatus对象,该对象保存了很多信息,包括被挂起的资源
			return startTransaction(def, transaction, debugEnabled, suspendedResources);
		}
		catch (RuntimeException | Error ex) {
			resume(null, suspendedResources);
			throw ex;
		}
	}
	else {
		// Create "empty" transaction: no actual transaction, but potentially synchronization.
		if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
			logger.warn("Custom isolation level specified but no actual transaction initiated; " +
					"isolation level will effectively be ignored: " + def);
		}
		boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
		return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
	}
}

doGetTransaction();

@Override
protected Object doGetTransaction() {
   DataSourceTransactionObject txObject = new DataSourceTransactionObject();
   txObject.setSavepointAllowed(isNestedTransactionAllowed());
   //new出来的DataSourceTransactionObject()去取数据库连接对象Connection对象(可能为空)
   ConnectionHolder conHolder =
         (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
  //new出来的DataSourceTransactionObject()set取到的数据库连接对象Connection对象
   txObject.setConnectionHolder(conHolder, false);
   return txObject;
}

跟下getResource

@Nullable
public static Object getResource(Object key) {
   Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
   Object value = doGetResource(actualKey);
   if (value != null && logger.isTraceEnabled()) {
      logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" +
            Thread.currentThread().getName() + "]");
   }
   return value;
}
doGetResource
@Nullable
private static Object doGetResource(Object actualKey) {
   Map<Object, Object> map = resources.get();
   if (map == null) {
      return null;
   }
   Object value = map.get(actualKey);
   // Transparently remove ResourceHolder that was marked as void...
   if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
      map.remove(actualKey);
      // Remove entire ThreadLocal if empty...
      if (map.isEmpty()) {
         resources.remove();
      }
      value = null;
   }
   return value;
}

这里的resources,key为DataSource,value就是数据库连接对象connection,存在ThreadLocal里面

private static final ThreadLocal<Map<Object, Object>> resources =
      new NamedThreadLocal<>("Transactional resources");

isExistingTransaction(transaction)

@Override
protected boolean isExistingTransaction(Object transaction) {
   DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
   return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
}

这里就是去取刚刚set的数据库连接对象connection,下面先看不存在事务的情况

startTransaction

private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
		boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {

	// 是否开启一个新的TransactionSynchronization
	boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);

	// 开启的这个事务的状态信息:
	// 事务的定义、用来保存数据库连接的对象、是否是新事务,是否是新的TransactionSynchronization
	DefaultTransactionStatus status = newTransactionStatus(
			definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);

	// 开启事务
	doBegin(transaction, definition);

	// 如果需要新开一个TransactionSynchronization,就把新创建的事务的一些状态信息设置到TransactionSynchronizationManager中
	prepareSynchronization(status, definition);
	return status;
}
doBegin();
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
   DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
   Connection con = null;

   try {
   		//之前没有数据库连接对象的情况下才获取新的数据库连接对象
      if (!txObject.hasConnectionHolder() ||
            txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
            
          //通过DataSource获取数据库连接对象
         Connection newCon = obtainDataSource().getConnection();
         if (logger.isDebugEnabled()) {
            logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
         }
         //将数据库连接对象放到txObject,并且设置为true,表示当前连接为新建连接
         txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
      }

      txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
      //数据库连接对象
      con = txObject.getConnectionHolder().getConnection();

	  //根据Transaction注解的配置信息,设置数据库隔离级别,设置是否只读
      Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
      txObject.setPreviousIsolationLevel(previousIsolationLevel);
      txObject.setReadOnly(definition.isReadOnly());

      // Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
      // so we don't want to do it unnecessarily (for example if we've explicitly
      // configured the connection pool to set it already).
      //判断数据库连接对象的AutoCommit是否为true
      if (con.getAutoCommit()) {
         txObject.setMustRestoreAutoCommit(true);
         if (logger.isDebugEnabled()) {
            logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
         }
         //数据库连接对象的AutoCommit改为false
         con.setAutoCommit(false);
      }

      prepareTransactionalConnection(con, definition);
      txObject.getConnectionHolder().setTransactionActive(true);

	  //设置超时时间
      int timeout = determineTimeout(definition);
      if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
         txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
      }

		//判断当前连接是否为新建连接,如果是新建连接,那么
      // Bind the connection holder to the thread.
      if (txObject.isNewConnectionHolder()) {
         TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
      }
   }

   catch (Throwable ex) {
      if (txObject.isNewConnectionHolder()) {
         DataSourceUtils.releaseConnection(con, obtainDataSource());
         txObject.setConnectionHolder(null, false);
      }
      throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
   }
}
bindResource
public static void bindResource(Object key, Object value) throws IllegalStateException {
   Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
   Assert.notNull(value, "Value must not be null");
   Map<Object, Object> map = resources.get();
   // set ThreadLocal Map if none found
   if (map == null) {
      map = new HashMap<>();
      resources.set(map);
   }
   Object oldValue = map.put(actualKey, value);
   // Transparently suppress a ResourceHolder that was marked as void...
   if (oldValue instanceof ResourceHolder && ((ResourceHolder) oldValue).isVoid()) {
      oldValue = null;
   }
   if (oldValue != null) {
      throw new IllegalStateException("Already value [" + oldValue + "] for key [" +
            actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
   }
   if (logger.isTraceEnabled()) {
      logger.trace("Bound value [" + value + "] for key [" + actualKey + "] to thread [" +
            Thread.currentThread().getName() + "]");
   }
}

这里会将key为DataSource,value为数据库连接对象connection的map存在 resources对象ThreadLocal里面

上述已经分析过了没有开启过事务的情况

如果开启过事务,就会执行如下方法

handleExistingTransaction

主要是挂起逻辑

private TransactionStatus handleExistingTransaction(
		TransactionDefinition definition, Object transaction, boolean debugEnabled)
		throws TransactionException {
	//总是非事务地执行,如果存在一个活动事务,则抛出异常
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
		throw new IllegalTransactionStateException(
				"Existing transaction found for transaction marked with propagation 'never'");
	}
	//总是非事务地执行,并挂起任何存在的事务。
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
		if (debugEnabled) {
			logger.debug("Suspending current transaction");
		}
		// 把当前事务挂起,其中就会把数据库连接对象从ThreadLocal中移除
		Object suspendedResources = suspend(transaction);
		boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
		return prepareTransactionStatus(
				definition, null, false, newSynchronization, debugEnabled, suspendedResources);
	}
	//总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
	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 {
			//新建连接,开启事务
			return startTransaction(definition, transaction, debugEnabled, suspendedResources);
		}
		catch (RuntimeException | Error beginEx) {
			resumeAfterBeginException(transaction, suspendedResources, beginEx);
			throw beginEx;
		}
	}
	//如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则开启一个新的事务。
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
		if (!isNestedTransactionAllowed()) {
			throw new NestedTransactionNotSupportedException(
					"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,mysql中的知识点,可忽略
			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.
			return startTransaction(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;
				throw new IllegalTransactionStateException("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()) {
				throw new IllegalTransactionStateException("Participating transaction with definition [" +
						definition + "] is not marked as read-only but existing transaction is");
			}
		}
	}

	// 如果依然是Propagation.REQUIRED
	boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
	return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
suspend
@Nullable
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
	// synchronizations是一个ThreadLocal<Set<TransactionSynchronization>>
	// 我们可以在任何地方通过TransactionSynchronizationManager给当前线程添加TransactionSynchronization,

	if (TransactionSynchronizationManager.isSynchronizationActive()) {
		// 调用TransactionSynchronization的suspend方法,并清空和返回当前线程中所有的TransactionSynchronization对象
		List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
		try {
			Object suspendedResources = null;
			if (transaction != null) {
				// 挂起事务,把transaction中的Connection清空,并把resources中的key-value进行移除,并返回数据库连接Connection对象
				//suspendedResources返回的就是被移除的Connection对象
				suspendedResources = doSuspend(transaction);
			}

			// 获取并清空当前线程中关于TransactionSynchronizationManager的设置
			String name = TransactionSynchronizationManager.getCurrentTransactionName();
			TransactionSynchronizationManager.setCurrentTransactionName(null);
			//挂起readOnly
			boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
			TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
			//挂起隔离级别
			Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
			TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
			//挂起活跃状态
			boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
			//这些对象都存在ThreadLocal中,下面可知
			TransactionSynchronizationManager.setActualTransactionActive(false);

		// 将当前线程中的数据库连接对象Connection、TransactionSynchronization对象、TransactionSynchronizationManager中的配置构造成一个对象
			// 表示被挂起的资源持有对象,持有了当前线程中的事务对象、TransactionSynchronization对象
			return new SuspendedResourcesHolder(
					suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
		}
		catch (RuntimeException | Error ex) {
			// doSuspend failed - original transaction is still active...
			doResumeSynchronization(suspendedSynchronizations);
			throw ex;
		}
	}
	else if (transaction != null) {
		// Transaction active but no synchronization active.
		Object suspendedResources = doSuspend(transaction);
		return new SuspendedResourcesHolder(suspendedResources);
	}
	else {
		// Neither transaction nor synchronization active.
		return null;
	}
}

ThreadLocal对象

private static final ThreadLocal<Map<Object, Object>> resources =
			new NamedThreadLocal<>("Transactional resources");

private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
      new NamedThreadLocal<>("Transaction synchronizations");

private static final ThreadLocal<String> currentTransactionName =
      new NamedThreadLocal<>("Current transaction name");

private static final ThreadLocal<Boolean> currentTransactionReadOnly =
      new NamedThreadLocal<>("Current transaction read-only status");

private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
      new NamedThreadLocal<>("Current transaction isolation level");

private static final ThreadLocal<Boolean> actualTransactionActive =
      new NamedThreadLocal<>("Actual transaction active");
doSuspendSynchronization

从synchronizations(一个ThreadLocal)中拿到自定义设置的TransactionSynchronization对象,一般不用,如需了解,可见本文档最下面的说明

private List<TransactionSynchronization> doSuspendSynchronization() {
	// 从synchronizations(一个ThreadLocal)中拿到所设置的TransactionSynchronization对象,一般不用
	List<TransactionSynchronization> suspendedSynchronizations =
			TransactionSynchronizationManager.getSynchronizations();

	// 调用TransactionSynchronization对象的suspend()
	for (TransactionSynchronization synchronization : suspendedSynchronizations) {
		synchronization.suspend();
	}

	// 清空synchronizations
	TransactionSynchronizationManager.clearSynchronization();

	// 把获取到的TransactionSynchronization返回
	return suspendedSynchronizations;
}
doSuspend

返回的就是原来的Connection对象

@Override
protected Object doSuspend(Object transaction) {
   DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
   //清掉原来的Connection对象
   txObject.setConnectionHolder(null);
   return TransactionSynchronizationManager.unbindResource(obtainDataSource());
}
unbindResource
public static Object unbindResource(Object key) throws IllegalStateException {
   Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
   //这里返回的就是原来的Connection对象
   Object value = doUnbindResource(actualKey);
   if (value == null) {
      throw new IllegalStateException(
            "No value for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
   }
   return value;
}
doUnbindResource

将移除的key的value,即原来的Connection对象,返回

@Nullable
private static Object doUnbindResource(Object actualKey) {
   Map<Object, Object> map = resources.get();
   if (map == null) {
      return null;
   }
   Object value = map.remove(actualKey);
   // Remove entire ThreadLocal if empty...
   if (map.isEmpty()) {
      resources.remove();
   }
   // Transparently suppress a ResourceHolder that was marked as void...
   if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
      value = null;
   }
   if (value != null && logger.isTraceEnabled()) {
      logger.trace("Removed value [" + value + "] for key [" + actualKey + "] from thread [" +
            Thread.currentThread().getName() + "]");
   }
   return value;
}

prepareTransactionInfo

protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
		@Nullable TransactionAttribute txAttr, String joinpointIdentification,
		@Nullable TransactionStatus status) {

	TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
	if (txAttr != null) {
		// We need a transaction for this method...
		if (logger.isTraceEnabled()) {
			logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
		}
		// The transaction manager will flag an error if an incompatible tx already exists.
		txInfo.newTransactionStatus(status);
	}
	else {
		// The TransactionInfo.hasTransaction() method will return false. We created it only
		// to preserve the integrity of the ThreadLocal stack maintained in this class.
		if (logger.isTraceEnabled()) {
			logger.trace("No need to create transaction for [" + joinpointIdentification +
					"]: This method is not transactional.");
		}
	}

	// We always bind the TransactionInfo to the thread, even if we didn't create
	// a new transaction here. This guarantees that the TransactionInfo stack
	// will be managed correctly even if no transaction was created by this aspect.
	// 把txInfo设置到ThreadLocal中
	txInfo.bindToThread();
	return txInfo;
}

txInfo.bindToThread();

private void bindToThread() {
   // Expose current TransactionStatus, preserving any existing TransactionStatus
   // for restoration after this transaction is complete.
   this.oldTransactionInfo = transactionInfoHolder.get();
   transactionInfoHolder.set(this);
}

private static final ThreadLocal<TransactionInfo> transactionInfoHolder =
			new NamedThreadLocal<>("Current aspect-driven transaction");

invocation.proceedWithInvocation();

这里就是执行程序员的代码逻辑,这里就不解释了

completeTransactionAfterThrowing

执行异常回滚逻辑

protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
   if (txInfo != null && txInfo.getTransactionStatus() != null) {
      if (logger.isTraceEnabled()) {
         logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
               "] after exception: " + ex);
      }
      //是否符合rollbackOn条件,这里是RuleBasedTransactionAttribute的rollbackOn
      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;
         }
      }
   }
}

rollbackOn

@Override
public boolean rollbackOn(Throwable ex) {
   if (logger.isTraceEnabled()) {
      logger.trace("Applying rules to determine whether transaction should rollback on " + ex);
   }

   RollbackRuleAttribute winner = null;
   int deepest = Integer.MAX_VALUE;

   if (this.rollbackRules != null) {
   //遍历所有的RollbackRuleAttribute,判断抛出的异常是否匹配
      for (RollbackRuleAttribute rule : this.rollbackRules) {
         int depth = rule.getDepth(ex);
         if (depth >= 0 && depth < deepest) {
            deepest = depth;
            winner = rule;
         }
      }
   }

   if (logger.isTraceEnabled()) {
      logger.trace("Winning rollback rule is: " + winner);
   }

	//没有匹配到规则,调用super.rollbackOn
   // User superclass behavior (rollback on unchecked) if no rule matches.
   if (winner == null) {
      logger.trace("No relevant rollback rule found: applying default rules");
      return super.rollbackOn(ex);
   }
	//可能是NoRollbackRuleAttribute,如果是NoRollbackRuleAttribute,则不会回滚,返回false
   return !(winner instanceof NoRollbackRuleAttribute);
}
super.rollbackOn
@Override
public boolean rollbackOn(Throwable ex) {
   return (ex instanceof RuntimeException || ex instanceof Error);
}

rollback

执行回滚

@Override
public final void rollback(TransactionStatus status) throws TransactionException {
   if (status.isCompleted()) {
      throw new IllegalTransactionStateException(
            "Transaction is already completed - do not call commit or rollback more than once per transaction");
   }

   DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
   processRollback(defStatus, false);
}
processRollback
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
	try {
		boolean unexpectedRollback = unexpected;

		try {
			triggerBeforeCompletion(status);

			// 比如mysql中的savepoint,可忽略
			if (status.hasSavepoint()) {
				if (status.isDebug()) {
					logger.debug("Rolling back transaction to savepoint");
				}
				// 回滚到上一个savepoint位置
				status.rollbackToHeldSavepoint();
			}
			//判断当前执行的方法是新开了一个事务
			else if (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 early
				if (!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 marker
		if (unexpectedRollback) {
			throw new UnexpectedRollbackException(
					"Transaction rolled back because it has been marked as rollback-only");
		}
	}
	finally {
		cleanupAfterCompletion(status);
	}
}
doRollback
@Override
protected void doRollback(DefaultTransactionStatus status) {
   DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
   Connection con = txObject.getConnectionHolder().getConnection();
   if (status.isDebug()) {
      logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
   }
   try {
      con.rollback();
   }
   catch (SQLException ex) {
      throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
   }
}

commitTransactionAfterReturning

这里就是commit的逻辑

protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
   if (txInfo != null && txInfo.getTransactionStatus() != null) {
      if (logger.isTraceEnabled()) {
         logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
      }
      txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
   }
}

commit

@Override
public final void commit(TransactionStatus status) throws TransactionException {
	if (status.isCompleted()) {
		throw new IllegalTransactionStateException(
				"Transaction is already completed - do not call commit or rollback more than once per transaction");
	}

	DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;

	// 可以通过TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();来设置
	// 事务本来是可以要提交的,但是可以强制回滚,在catch的代码块中可设置RollbackOnly,用的不多,可忽略
	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);
}
processCommit
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
   try {
      boolean beforeCompletionInvoked = false;

      try {
         boolean unexpectedRollback = false;
         prepareForCommit(status);
         //调用自定义的同步器,可忽略
         triggerBeforeCommit(status);
         //不管提交还是回滚都会调用
         triggerBeforeCompletion(status);
         beforeCompletionInvoked = true;

		//Savepoint相关,可忽略
         if (status.hasSavepoint()) {
            if (status.isDebug()) {
               logger.debug("Releasing transaction savepoint");
            }
            unexpectedRollback = status.isGlobalRollbackOnly();
            status.releaseHeldSavepoint();
         }
         else if (status.isNewTransaction()) {
            if (status.isDebug()) {
               logger.debug("Initiating transaction commit");
            }
            unexpectedRollback = status.isGlobalRollbackOnly();
            //这里就是真正的提交代码
            doCommit(status);
         }
         else if (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) {
            throw new UnexpectedRollbackException(
                  "Transaction silently rolled back because it has been marked as rollback-only");
         }
      }
      catch (UnexpectedRollbackException ex) {
         // can only be caused by doCommit
         triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
         throw ex;
      }
      catch (TransactionException ex) {
         // can only be caused by doCommit
         if (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);
   }
}
doCommit(status);
@Override
protected void doCommit(DefaultTransactionStatus status) {
   DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
   //获取Connection对象
   Connection con = txObject.getConnectionHolder().getConnection();
   if (status.isDebug()) {
      logger.debug("Committing JDBC transaction on Connection [" + con + "]");
   }
   try {
   //Connection对象commit
      con.commit();
   }
   catch (SQLException ex) {
      throw new TransactionSystemException("Could not commit JDBC transaction", ex);
   }
}
cleanupAfterCompletion
private void cleanupAfterCompletion(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());
   }
}

resume

protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
      throws TransactionException {

   if (resourcesHolder != null) {
      Object suspendedResources = resourcesHolder.suspendedResources;
      if (suspendedResources != null) {
      	//把挂起资源重新绑定到当前线程中去
         doResume(transaction, suspendedResources);
      }
      List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
      if (suspendedSynchronizations != null) {
      	//恢复挂起资源的名字,隔离级别,标记等属性
         TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);
         TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);
         TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);
         TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
         //执行resume()
         doResumeSynchronization(suspendedSynchronizations);
      }
   }
}

doResume

@Override
protected void doResume(@Nullable Object transaction, Object suspendedResources) {
   TransactionSynchronizationManager.bindResource(obtainDataSource(), suspendedResources);
}

bindResource

重新绑定到当前线程中去

public static void bindResource(Object key, Object value) throws IllegalStateException {
   Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
   Assert.notNull(value, "Value must not be null");
   Map<Object, Object> map = resources.get();
   // set ThreadLocal Map if none found
   if (map == null) {
      map = new HashMap<>();
      resources.set(map);
   }
   Object oldValue = map.put(actualKey, value);
   // Transparently suppress a ResourceHolder that was marked as void...
   if (oldValue instanceof ResourceHolder && ((ResourceHolder) oldValue).isVoid()) {
      oldValue = null;
   }
   if (oldValue != null) {
      throw new IllegalStateException("Already value [" + oldValue + "] for key [" +
            actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
   }
   if (logger.isTraceEnabled()) {
      logger.trace("Bound value [" + value + "] for key [" + actualKey + "] to thread [" +
            Thread.currentThread().getName() + "]");
   }
}

doResumeSynchronization

private void doResumeSynchronization(List<TransactionSynchronization> suspendedSynchronizations) {
   TransactionSynchronizationManager.initSynchronization();
   for (TransactionSynchronization synchronization : suspendedSynchronizations) {
      synchronization.resume();
      //设置同步器
      TransactionSynchronizationManager.registerSynchronization(synchronization);
   }
}
cleanupAfterCompletion
private void cleanupAfterCompletion(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());
	}
}

Spring事务基本执行原理

一个Bean在执行Bean的创建生命周期时,会经过InfrastructureAdvisorAutoProxyCreator的初始化后的方法,会判断当前当前Bean对象是否和BeanFactoryTransactionAttributeSourceAdvisor匹配,匹配逻辑为判断该Bean的类上是否存在@Transactional注解,或者类中的某个方法上是否存在@Transactional注解,如果存在则表示该Bean需要进行动态代理产生一个代理对象作为Bean对象。

该代理对象在执行某个方法时,会再次判断当前执行的方法是否和BeanFactoryTransactionAttributeSourceAdvisor匹配,如果匹配则执行该Advisor中的TransactionInterceptor的invoke()方法,执行基本流程为:

  1. 利用所配置的PlatformTransactionManager事务管理器新建一个数据库连接
  2. 修改数据库连接的autocommit为false
  3. 执行MethodInvocation.proceed()方法,简单理解就是执行业务方法,其中就会执行sql
  4. 如果没有抛异常,则提交
  5. 如果抛了异常,则回滚

Spring事务详细执行流程

Spring事务执行流程图:https://www.processon.com/view/link/5fab6edf1e0853569633cc06

Spring事务传播机制原理

在开发过程中,经常会出现一个方法调用另外一个方法,那么这里就涉及到了多种场景,比如a()调用b():

  1. a()和b()方法中的所有sql需要在同一个事务中吗?
  2. a()和b()方法需要单独的事务吗?
  3. a()需要在事务中执行,b()还需要在事务中执行吗?
  4. 等等情况...

所以,这就要求Spring事务能支持上面各种场景,这就是Spring事务传播机制的由来。那Spring事务传播机制是如何实现的呢?

先来看上述几种场景中的一种情况,a()在一个事务中执行,调用b()方法时需要新开一个事务执行:

  1. 首先,代理对象执行a()方法前,先利用事务管理器新建一个数据库连接a
  2. 将数据库连接a的autocommit改为false
  3. 把数据库连接a设置到ThreadLocal中
  4. 执行a()方法中的sql
  5. 执行a()方法过程中,调用了b()方法(注意用代理对象调用b()方法)
    1. 代理对象执行b()方法前,判断出来了当前线程中已经存在一个数据库连接a了,表示当前线程其实已经拥有一个Spring事务了,则进行挂起
    2. 挂起就是把ThreadLocal中的数据库连接a从ThreadLocal中移除,并放入一个挂起资源对象
    3. 挂起完成后,再次利用事务管理器新建一个数据库连接b
    4. 将数据库连接b的autocommit改为false
    5. 把数据库连接b设置到ThreadLocal中
    6. 执行b()方法中的sql
    7. b()方法正常执行完,则从ThreadLocal中拿到数据库连接b进行提交
    8. 提交之后会恢复所挂起的数据库连接a,这里的恢复,其实只是把在挂起资源对象中所保存的数据库连接a再次设置到ThreadLocal中
  6. a()方法正常执行完,则从ThreadLocal中拿到数据库连接a进行提交

这个过程中最为核心的是:在执行某个方法时,判断当前是否已经存在一个事务,就是判断当前线程的ThreadLocal中是否存在一个数据库连接对象,如果存在则表示已经存在一个事务了。

posted on 2022-03-08 23:17  路仁甲  阅读(71)  评论(0编辑  收藏  举报