/**
* 在調用process方法的時候會調用到這裡
*/
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
// 默認是PROXY。往Spring容器中添加了兩個Bean:AutoProxyRegistrar、ProxyTransactionManagementConfiguration
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
// 表示不用動態代理技術,用ASPECTJ技術,比較麻煩了
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
AutoProxyRegistrar的Bean源碼分析
/**
* 這個類實現了ImportBeanDefinitionRegistrar,他在啟動的時候會調用registerBeanDefinitions方法。
* 最核心的邏輯是往Spring容器中註冊了一個InfrastructureAdvisorAutoProxyCreator的Bean。
* InfrastructureAdvisorAutoProxyCreator繼承了AbstractAdvisorAutoProxyCreator,所以這個類的主要作用就是開啟自動代理的作用,也就是一個BeanPostProcessor,會在初始化後步驟中去尋找Advisor類型的Bean,並判斷當前某個Bean是否有匹配的Advisor,是否需要利用動態代理產生一個代理對象。
*/
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
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) {
// 註冊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));
}
}
}
導入的ProxyTransactionManagementConfiguration源碼分析
/**
* ProxyTransactionManagementConfiguration是一個配置類,它又定義了另外三個bean:
* BeanFactoryTransactionAttributeSourceAdvisor:一個Advisor
* AnnotationTransactionAttributeSource:相當於BeanFactoryTransactionAttributeSourceAdvisor中的Pointcut
* TransactionInterceptor:相當於BeanFactoryTransactionAttributeSourceAdvisor中的Advice
*/
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
// 定義一個Advisor的Bean
@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;
}
// 定義Advisor的Pointcut
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
// AnnotationTransactionAttributeSource中定義了一個Pointcut
// 並且AnnotationTransactionAttributeSource可以用來解析@Transactional註解,並得到一個RuleBasedTransactionAttribute對象
return new AnnotationTransactionAttributeSource();
}
// 定義Advisor的Advice
// 開啟事務、回滾、提交都在這個TransactionInterceptor中
@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;
}
}
使用用到的Pointcut源碼分析
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
/**
* pointcut就是一個new TransactionAttributeSourcePointcut對象
*/
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
/**
* 獲取pointcut採用的是內部類的方式構建
*/
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
/**
* 構建Pointcut用到的類
*/
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
// 外部構造方法調用到這裡,其實就是設置new TransactionAttributeSourceClassFilter()
// 這裡面主要進行類的判斷
protected TransactionAttributeSourcePointcut() {
setClassFilter(new TransactionAttributeSourceClassFilter());
}
// 判斷方法是否匹配
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 調用外部重寫的方法
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
// 具體的匹配邏輯
private class TransactionAttributeSourceClassFilter implements ClassFilter {
@Override
public boolean matches(Class<?> clazz) {
// 事務內部的一些類,直接返回false
if (TransactionalProxy.class.isAssignableFrom(clazz) ||
TransactionManager.class.isAssignableFrom(clazz) ||
PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
return false;
}
// 調用外部重寫的方法
TransactionAttributeSource tas = getTransactionAttributeSource();
// 判斷有沒有@Transaction註解
return (tas == null || tas.isCandidateClass(clazz));
}
}
}
/**
* 源碼位置:org.springframework.transaction.annotation.AnnotationTransactionAttributeSource.isCandidateClass(Class<?>)
* 判斷是否能成為候選者
*/
public boolean isCandidateClass(Class<?> targetClass) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
if (parser.isCandidateClass(targetClass)) {
return true;
}
}
return false;
}
/**
* 源碼位置:org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource.getTransactionAttribute(Method, Class<?>)
* 判斷當前類上面是否有@Transactional註解
*/
public boolean isCandidateClass(Class<?> targetClass) {
return AnnotationUtils.isCandidateClass(targetClass, Transactional.class);
}
/**
* 源碼位置:org.springframework.transaction.annotation.SpringTransactionAnnotationParser.isCandidateClass(Class<?>)
* 獲取方法上或者類上是否有@Transaction註解
*/
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// Object類直接返回null
if (method.getDeclaringClass() == Object.class) {
return null;
}
// First, see if we have a cached value.
// 檢查快取里的結果,快取里存了當前類和方法是否存在Transactional註解
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// Value will either be canonical value indicating there is no transaction attribute,
// or an actual transaction attribute.
// 快取中沒有,直接返回null
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
}
else {
// We need to work it out.
// 解析。實際對象為RuleBasedTransactionAttribute
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
// 為空,快取一個空的
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
if (txAttr instanceof DefaultTransactionAttribute) {
DefaultTransactionAttribute dta = (DefaultTransactionAttribute) txAttr;
dta.setDescriptor(methodIdentification);
dta.resolveAttributeStrings(this.embeddedValueResolver);
}
if (logger.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
// 不為空,快取結果
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
最終執行的Advisor:TransactionInterceptor源碼分析
/**
* 源碼位置:org.springframework.transaction.interceptor.TransactionInterceptor.invoke(MethodInvocation)
*/
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();
}
});
}
/**
* 具體的執行程式碼
*/
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對象。事務的開啟,提交,回滾都會用到TransactionManager對象。
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或被代理對象中的方法
retVal = invocation.proceedWithInvocation(); //test
}
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;
}
}
/**
* 創建事務的邏輯
*/
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// If no name specified, apply method identification as transaction name.
// 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);
}
獲取(開啟)事務的邏輯
/**
* 獲取事務的邏輯
* 源碼位置:org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(TransactionDefinition)
* definition:Transaction註解的資訊的對象
*/
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// Use defaults if no transaction definition given.
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
// 從ThreadLocal中拿到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.
// 配置的資料庫返回的超時時間小於-1,拋異常。
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.
// 當前不存在事務,並且配置的傳播機製為PROPAGATION_MANDATORY(支援當前事務,如果沒有事務拋出異常),拋異常
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
// 在當前Thread中沒有事務的前提下,以下三個是等價的。
// PROPAGATION_REQUIRED :支援當前事務,如果沒有事務會創建一個新的事務
// PROPAGATION_REQUIRES_NEW :創建一個新的事務並掛起當前事務
// PROPAGATION_NESTED: 如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則創建一個事務。
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 沒有事務需要掛起,不過TransactionSynchronization有可能需要掛起。直接調用TransactionSynchronizationManager.initSynchronization方法會有需要被掛起的。
// 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);
}
}
/**
* 開啟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;
}
/**
* 開啟事務!DataSource層面
* 源碼位置:org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(Object, TransactionDefinition)
*/
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");
}
// 設置到DataSourceTransactionObject。注意這裡設置的true,表示txObject的鏈接一個新的
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。autocommit為true的時候設置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<Map<Object, Object>>,事務管理器中的設置的DataSource對象為key,資料庫連接對象為value
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);
}
}