开启Spring事务本质上就是增加了一个Advisor,在使用@EnableTransactionManagement注解来开启Spring事务时,该注解代理的功能就是向Spring容器中添加了两个Bean
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement { ... }
/**
* Selects which implementation of {@link AbstractTransactionManagementConfiguration}
* should be used based on the value of {@link EnableTransactionManagement#mode} on the
* importing {@code @Configuration} class.
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
* @see EnableTransactionManagement
* @see ProxyTransactionManagementConfiguration
* @see TransactionManagementConfigUtils#TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME
* @see TransactionManagementConfigUtils#JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME
*/
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector {
/**
* Returns {@link ProxyTransactionManagementConfiguration} or
* {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}
* and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},
* respectively.
*/
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
// 默认是PROXY
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
// 表示不用动态代理技术,用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);
}
}
1、AutoProxyRegistrar
向Spring容器中注册了一个InfrastructureAdvisorAutoProxyCreator的Bean
InfrastructureAdvisorAutoProxyCreator 继承了AbstractAdvisorAutoProxyCreator
主要作用:开启自动代理
在初始化后寻找Advisor类型的Bean,并检查当前Bean是否有匹配的Advisor,是否需要动态代理创建代理对象
/**
* Registers an auto proxy creator against the current {@link BeanDefinitionRegistry}
* as appropriate based on an {@code @Enable*} annotation having {@code mode} and
* {@code proxyTargetClass} attributes set to the correct values.
*
* @author Chris Beams
* @since 3.1
* @see org.springframework.cache.annotation.EnableCaching
* @see org.springframework.transaction.annotation.EnableTransactionManagement
*/
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
private final Log logger = LogFactory.getLog(getClass());
/**
* Register, escalate, and configure the standard auto proxy creator (APC) against the
* given registry. Works by finding the nearest annotation declared on the importing
* {@code @Configuration} class that has both {@code mode} and {@code proxyTargetClass}
* attributes. If {@code mode} is set to {@code PROXY}, the APC is registered; if
* {@code proxyTargetClass} is set to {@code true}, then the APC is forced to use
* subclass (CGLIB) proxying.
* Several {@code @Enable*} annotations expose both {@code mode} and
* {@code proxyTargetClass} attributes. It is important to note that most of these
* capabilities end up sharing a {@linkplain AopConfigUtils#AUTO_PROXY_CREATOR_BEAN_NAME
* single APC}. For this reason, this implementation doesn't "care" exactly which
* annotation it finds -- as long as it exposes the right {@code mode} and
* {@code proxyTargetClass} attributes, the APC can be registered and configured all
* the same.
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set 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));
}
}
}
// AopConfigUtils#registerAutoProxyCreatorIfNecessary
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
// AopConfigUtils#registerAutoProxyCreatorIfNecessary
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
// AopConfigUtils#forceAutoProxyCreatorToUseClassProxying
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
// AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator"
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
2、ProxyTransactionManagementConfiguration
是一个配置类,内部定义了三个Bean:
BeanFactoryTransactionAttributeSourceAdvisor:一个Advisor
AnnotationTransactionAttributeSource:相当于BeanFactoryTransactionAttributeSourceAdvisor中的Pointcut,判断某个类或者方法上面是否存在@Transactional注解,注意这里并没有解析
TransactionInterceptor:相当于BeanFactoryTransactionAttributeSourceAdvisor中的 Advice,当某个类中存在@Transactional注解,就会产生一个代理对象作为Bean,在执行代理对象的某个方法时会进入到TransactionInterceptor的invoke()方法中
invoke()方法里面就会创建数据库连接、关闭自动提交、事务提交和回滚等
/**
* {@code @Configuration} class that registers the Spring infrastructure beans
* necessary to enable proxy-based annotation-driven transaction management.
*
* @author Chris Beams
* @author Sebastien Deleuze
* @since 3.1
* @see EnableTransactionManagement
* @see TransactionManagementConfigurationSelector
*/
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@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.getNumber("order"));
}
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
// AnnotationTransactionAttributeSource中定义了一个Pointcut
// 并且AnnotationTransactionAttributeSource可以用来解析@Transactional注解,并得到一个RuleBasedTransactionAttribute对象
return new AnnotationTransactionAttributeSource();
}
@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;
}
}
InfrastructureAdvisorAutoProxyCreator也是一个BeanPostProcessor(最终实现SmartInstantiationAwareBeanPostProcessor),在Bean的生命周期初始化后步骤时,会去判断是否需要创建代理对象
判断依据:当前Bean和BeanFactoryTransactionAttributeSourceAdvisor匹配,简单点就是当前Bean的类或者方法上面有没有@Transactional注解,有就匹配
在代理对象执行某个方法时,会再次判断当前执行方法和BeanFactoryTransactionAttributeSourceAdvisor是否匹配,如果匹配则执行该Advisor中的TransactionInterceptor的invoke()方法,执行流程:
(再次判断是考虑到一个类中可能有多个方法,有的方法有@Transactional注解,有的没有)
1、利用所配置的PlatformTransactionManager事务管理器新建一个数据库连接,注意TransactionManager有限制的必须是PlatformTransactionManager,然后会生成一个joinpointIdentification作为事务的名字
2、修改数据库连接的autocommit为false
3、执行MethodInvocation.proceed()方法,简单理解就是执行业务方法,其中就会执行sql
4、如果没有抛异常,则提交,执行完finally中的方法后再进行提交
5、如果抛了异常,则回滚,执行完finally中的方法后再抛出异常
开发过程中,经常会出现一个方法调用另外一个方法,那么就涉及到了多种场景。比如多个方法需要在同一个事务中执行;每个方法要在单独的事务中执行;有的方法需要事务,有的不需要事务;还有很多更复杂情况。Spring为了支持各种场景,也就有了Spring事务传播机制
场景分析,假设a()方法在事务执行中,调用b()方法需要开启一个新事务执行:
1、首先,代理对象执行a()方法前,先利用事务管理器新建一个数据库连接a
2、将数据库连接a的autocommit改为false
3、把数据库连接a设置到ThreadLocal中
4、执行a()方法中的sql
5、执行a()方法过程中,调用了b()方法(注意用代理对象调用b()方法)
a)代理对象执行b()方法前,判断出来了当前线程中已经存在一个数据库连接a了,表示当前线程其实已经拥有一个Spring事务了,则进行挂起
b)挂起就是把ThreadLocal中的数据库连接a从ThreadLocal中移除,并放入一个挂起资源对象中(就是事务同步管理器:TransactionSynchronizationManager)
c)挂起完成后,再次利用事务管理器新建一个数据库连接b
d)将数据库连接b的autocommit改为false
e)把数据库连接b设置到ThreadLocal中
f)执行b()方法中的sql
g)b()方法正常执行完,则从ThreadLocal中拿到数据库连接b进行提交
h)提交之后会恢复所挂起的数据库连接a,这里的恢复,其实只是把在挂起资源对象中所保存的数据库连接a再次设置到ThreadLocal中
6、a()方法正常执行完,则从ThreadLocal中拿到数据库连接a进行提交
过程核心:在执行某个方法时,判断当前是否已经存在一个事务,就是判断当前线程的ThreadLocal中是否存在一个数据库连接对象,如果存在则表示已经存在一个事务了。
代理对象执行方法时,源码invoke入口:
// TransactionInterceptor#invoke
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, new CoroutinesInvocationCallback() {
@Override
@Nullable
public Object proceedWithInvocation() throws Throwable {
// 执行后续的Interceptor,以及被代理的方法
return invocation.proceed(); // test() sql
}
@Override
public Object getTarget() {
return invocation.getThis();
}
@Override
public Object[] getArguments() {
return invocation.getArguments();
}
});
}
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// currentInterceptorIndex初始值为-1,每调用一个interceptor就会加1
// 当调用完了最后一个interceptor后就会执行被代理方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// currentInterceptorIndex初始值为-1
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor
// 如果没有匹配则递归调用proceed()方法,调用下一个interceptor
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
// 动态匹配,根据方法参数匹配
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
// 不匹配则执行下一个MethodInterceptor
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
// 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归
// 比如MethodBeforeAdviceInterceptor
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
TransactionInterceptor#invokeWithinTransaction:
/**
* General delegate for around-advice-based subclasses, delegating to several other template
* methods on this class. Able to handle {@link CallbackPreferringPlatformTransactionManager}
* as well as regular {@link PlatformTransactionManager} implementations and
* {@link ReactiveTransactionManager} implementations for reactive return types.
* @param method the Method being invoked
* @param targetClass the target class that we're invoking the method on
* @param invocation the callback to use for proceeding with the target invocation
* @return the return value of the method, if any
* @throws Throwable propagated from the target invocation
*/
@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) {
... ...
}
// 把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或被代理对象中的方法
retVal = invocation.proceedWithInvocation(); // test() sql
}
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();
... ...
}
}
/**
* Create a transaction if necessary based on the given TransactionAttribute.
* Allows callers to perform custom TransactionAttribute lookups through
* the TransactionAttributeSource.
* @param txAttr the TransactionAttribute (may be {@code null})
* @param joinpointIdentification the fully qualified method name
* (used for monitoring and logging purposes)
* @return a TransactionInfo object, whether or not a transaction was created.
* The {@code hasTransaction()} method on TransactionInfo can be used to
* tell if there was a transaction created.
* @see #getTransactionAttributeSource()
*/
@SuppressWarnings("serial")
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// 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;
if (txAttr != null) {
if (tm != null) {
//
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);
}
关键方法getTransaction(txAttr):
/**
* This implementation handles propagation behavior. Delegates to
* {@code doGetTransaction}, {@code isExistingTransaction}
* and {@code doBegin}.
* @see #doGetTransaction
* @see #isExistingTransaction
* @see #doBegin
*/
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// Use defaults if no transaction definition given.
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
// 得到一个新的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);
}
// Check definition settings for new transaction.
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
}
// 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中没有事务的前提下,以下三个是等价的
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 没有事务需要挂起,不过TransactionSynchronization有可能需要挂起
// suspendedResources表示当前线程被挂起的资源持有对象(数据库连接、TransactionSynchronization)
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);
}
}
/**
* Create a TransactionStatus for an existing transaction.
*/
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
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);
}
开启事务startTransaction:
/**
* Start a new transaction.
*/
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;
}
// DataSourceTransactionManager#doBegin
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
// 如果当前线程中所使用的DataSource还没有创建过数据库连接,就获取一个新的数据库连接
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
Connection newCon = obtainDataSource().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
// 根据@Transactional注解中的设置,设置Connection的readOnly与隔离级别
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为false
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
if (logger.isDebugEnabled()) {
logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
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.
// 把新建的数据库连接设置到resources中,resources就是一个ThreadLocal
以非事务方式运行:表示以非Spring事务运行,表示在执行这个方法时,Spring事务管理器不会去建立数据库连接,执行sql时,由Mybatis或JdbcTemplate自己来建立数据库连接来执行 sql。
事务1内部调用事务2场景,无异常
@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()方法进行提交
事务1内部调用事务2场景,事务1内部有异常
@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都会回滚掉
事务1内部调用事务2场景,事务2内部有异常
@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都会回滚掉
对于事务1而言,userService.a(); 这个方法的调用抛出了异常,所以事务1也要回滚
@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都回滚了
正常情况下,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();
}
事务仍然回滚,捕获异常是为了给客户端更好的提示
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提交或回滚成功了");
System.out.println("a提交或回滚成功了");
}
});
jdbcTemplate.execute("insert into t1 values(2,2,2,2,'2')");
System.out.println("a");
}
}