Java中SpringBoot的@Transactional原理
一、@Transactional的使用
- 加在方法上:方法內(nèi)的所有操作處于一個(gè)事務(wù)中
- 加在類上
- 該類的所有public修飾的方法都具有共享事務(wù)屬性
- 如果方法和類上都有事務(wù)注解,方法上的事務(wù)注解優(yōu)先
二、@Transactional原理
Springboot目前最為流行,它的約定大于配置的特性深受大家喜歡,注解驅(qū)動(dòng)開發(fā)已成為主流。面向元數(shù)據(jù)遍歷已經(jīng)成為越來越多開發(fā)者的偏好,因此原理從Springboot的EnableTransactionManagement注解說起
1、@EnableTransactionManagement
表示開啟事務(wù)管理
@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; }
通過Import導(dǎo)入了TransactionManagementConfigurationSelector類,其中默認(rèn)的AdviceMode為AdviceMode.PROXY,即默認(rèn)使用JDK的動(dòng)態(tài)代理生成代理類。
2、TransactionManagementConfigurationSelector
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> { /** * 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) { //根據(jù)上面注解的默認(rèn)配置,adviceMode默認(rèn)為PROXY case PROXY: 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); } }
TransactionManagementConfigurationSelector繼承自AdviceModeImportSelector類,實(shí)現(xiàn)selectImports方法可以注入對(duì)應(yīng)的bean,根據(jù)EnableTransactionManagement注解的默認(rèn)配置,adviceMode默認(rèn)為PROXY。所以這里會(huì)注入AutoProxyRegistrar和ProxyTransactionManagementConfiguration這兩個(gè)類
- AutoProxyRegistrar
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. * <p>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; // 這里面需要特別注意的是:這里是拿到所有的注解類型~~~而不是只拿@EnableAspectJAutoProxy這個(gè)類型的 // 原因:因?yàn)閙ode、proxyTargetClass等屬性會(huì)直接影響到代理得方式,而擁有這些屬性的注解至少有: // @EnableTransactionManagement、@EnableAsync、@EnableCaching等~~~~ // 甚至還有啟用AOP的注解:@EnableAspectJAutoProxy它也能設(shè)置`proxyTargetClass`這個(gè)屬性的值,因此也會(huì)產(chǎn)生關(guān)聯(lián)影響~ Set<String> annTypes = importingClassMetadata.getAnnotationTypes(); for (String annType : annTypes) { AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType); if (candidate == null) { continue; } //獲取mode和proxyTargetClass的屬性 Object mode = candidate.get("mode"); Object proxyTargetClass = candidate.get("proxyTargetClass"); //如果存在這兩個(gè)屬性且類型符合要求 if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) { candidateFound = true; if (mode == AdviceMode.PROXY) { //向容器注入的是一個(gè)InfrastructureAdvisorAutoProxyCreator,它主要是讀取Advisor類,并對(duì)符合的bean進(jìn)行二次代理 //如果出現(xiàn)多次的話,這里不是覆蓋的形式,而是以第一次的為主 //當(dāng)然它內(nèi)部有做等級(jí)的提升之類的 AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry); //看要不要強(qiáng)制使用CGLIB的方式(這個(gè)屬性若出現(xiàn)多次,是會(huì)是覆蓋的形式) if ((Boolean) proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); return; } } } } //如果一個(gè)都沒有找到則打印info日志 //可能是自己注入這個(gè)類,而不是使用注解去注入 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)); } } }
主要作用就是往Spring容器注入了一個(gè)自動(dòng)代理創(chuàng)建器:org.springframework.aop.config.internalAutoProxyCreator
,并且看看是采用CGLIB還是JDK代理
- ProxyTransactionManagementConfiguration
@Configuration(proxyBeanMethods = false) 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.<Integer>getNumber("order")); } return advisor; } @Bean @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public TransactionAttributeSource transactionAttributeSource() { 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; } }
這里是往容器中注入事務(wù)相關(guān)的bean
- BeanFactoryTransactionAttributeSourceAdvisor:事務(wù)的核心,下面分析
- TransactionAttributeSource:事務(wù)屬性源
- TransactionInterceptor:事務(wù)攔截器,它是個(gè)MethodInterceptor。(我們可以自定義個(gè)beanName一模一樣的TransactionInterceptor來覆蓋默認(rèn)的事務(wù)攔截器)
(我們可以自定義個(gè)beanName一模一樣的TransactionInterceptor來覆蓋默認(rèn)的事務(wù)攔截器)
再看父類AbstractTransactionManagementConfiguration
@Configuration public abstract class AbstractTransactionManagementConfiguration implements ImportAware { @Nullable protected AnnotationAttributes enableTx; /** * Default transaction manager, as configured through a {@link TransactionManagementConfigurer}. */ @Nullable protected TransactionManager txManager; @Override public void setImportMetadata(AnnotationMetadata importMetadata) { this.enableTx = AnnotationAttributes.fromMap( importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false)); if (this.enableTx == null) { throw new IllegalArgumentException( "@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName()); } } //這里可以通過配置文件注入一個(gè)默認(rèn)的事務(wù)管理器 @Autowired(required = false) void setConfigurers(Collection<TransactionManagementConfigurer> configurers) { if (CollectionUtils.isEmpty(configurers)) { return; } //最多只允許配置一個(gè) if (configurers.size() > 1) { throw new IllegalStateException("Only one TransactionManagementConfigurer may exist"); } TransactionManagementConfigurer configurer = configurers.iterator().next(); this.txManager = configurer.annotationDrivenTransactionManager(); } //注冊(cè)一個(gè)監(jiān)聽器工廠,用以支持@TransactionalEventListener注解標(biāo)注的方法,來監(jiān)聽事務(wù)相關(guān)的事件 @Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public static TransactionalEventListenerFactory transactionalEventListenerFactory() { return new TransactionalEventListenerFactory(); } }
- BeanFactoryTransactionAttributeSourceAdvisor
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor { @Nullable private TransactionAttributeSource transactionAttributeSource; //切面:決定了哪些類會(huì)被切入,從而生成的代理對(duì)象 private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() { @Override @Nullable protected TransactionAttributeSource getTransactionAttributeSource() { return transactionAttributeSource; } }; // 可議手動(dòng)設(shè)置一個(gè)事務(wù)屬性源 public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) { this.transactionAttributeSource = transactionAttributeSource; } //可以指定ClassFilter 默認(rèn)情況下:ClassFilter classFilter = ClassFilter.TRUE; 匹配所有的類的 public void setClassFilter(ClassFilter classFilter) { this.pointcut.setClassFilter(classFilter); } //此處pointcut就是使用自己的這個(gè)pointcut去切入 @Override public Pointcut getPointcut() { return this.pointcut; } }
我們繼續(xù)查看TransactionAttributeSourcePointcut類
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable { protected TransactionAttributeSourcePointcut() { setClassFilter(new TransactionAttributeSourceClassFilter()); } @Override public boolean matches(Method method, Class<?> targetClass) { TransactionAttributeSource tas = getTransactionAttributeSource(); return (tas == null || tas.getTransactionAttribute(method, targetClass) != null); } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (!(other instanceof TransactionAttributeSourcePointcut)) { return false; } TransactionAttributeSourcePointcut otherPc = (TransactionAttributeSourcePointcut) other; return ObjectUtils.nullSafeEquals(getTransactionAttributeSource(), otherPc.getTransactionAttributeSource()); } @Override public int hashCode() { return TransactionAttributeSourcePointcut.class.hashCode(); } @Override public String toString() { return getClass().getName() + ": " + getTransactionAttributeSource(); } //由子類提供事務(wù)屬性源 @Nullable protected abstract TransactionAttributeSource getTransactionAttributeSource(); /** * {@link ClassFilter} that delegates to {@link TransactionAttributeSource#isCandidateClass} * for filtering classes whose methods are not worth searching to begin with. */ private class TransactionAttributeSourceClassFilter implements ClassFilter { @Override public boolean matches(Class<?> clazz) { // 實(shí)現(xiàn)了如下三個(gè)接口的子類,就不需要被代理了 直接放行 // TransactionalProxy它是SpringProxy的子類。如果是被TransactionProxyFactoryBean生產(chǎn)出來的Bean,就會(huì)自動(dòng)實(shí)現(xiàn)此接口,那么就不會(huì)被這里再次代理了 // PlatformTransactionManager:spring抽象的事務(wù)管理器 // PersistenceExceptionTranslator對(duì)RuntimeException轉(zhuǎn)換成DataAccessException的轉(zhuǎn)換接口 if (TransactionalProxy.class.isAssignableFrom(clazz) || PlatformTransactionManager.class.isAssignableFrom(clazz) || PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) { return false; } // 重要:拿到事務(wù)屬性源~~~~~~ // 如果tas == null表示沒有配置事務(wù)屬性源,那是全部匹配的,也就是說所有的方法都匹配 // 或者 標(biāo)注了@Transaction這樣的注解的方法才會(huì)給與匹配 TransactionAttributeSource tas = getTransactionAttributeSource(); return (tas == null || tas.isCandidateClass(clazz)); } } }
關(guān)于matches方法的調(diào)用時(shí)機(jī):只要是容器內(nèi)的每個(gè)Bean,都會(huì)經(jīng)過AbstractAutoProxyCreator#postProcessAfterInitialization
從而會(huì)調(diào)用wrapIfNecessary
方法,因此容器內(nèi)所有的Bean的所有方法在容器啟動(dòng)時(shí)候都會(huì)執(zhí)行此matche方法。
3、TransactionInterceptor
事務(wù)處理的核心邏輯就在這個(gè)攔截器里面,我們先看下Spring事務(wù)的三個(gè)接口
- TransactionStatus:代表一個(gè)事務(wù)的具體運(yùn)行狀態(tài)、以及還原點(diǎn)
public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable { //判斷該事務(wù)里面是否含有還原點(diǎn) boolean hasSavepoint(); //將基礎(chǔ)會(huì)話刷新到數(shù)據(jù)存儲(chǔ) @Override void flush(); } public interface TransactionExecution { //判斷當(dāng)前的事務(wù)是否是新事務(wù) boolean isNewTransaction(); //設(shè)置這個(gè)目的是為了讓事務(wù)的唯一結(jié)果是進(jìn)行回滾。 //因此如果你在外層給try catche住不讓事務(wù)回滾,就會(huì)拋出你可能常見的異常: //Transaction rolled back because it has been marked as rollback-only void setRollbackOnly(); //判斷事務(wù)的是不是必須回滾 boolean isRollbackOnly(); //判斷事務(wù)是否結(jié)果(不管是commit還是rollback) boolean isCompleted(); }
- TransactionDefinition:用于描述隔離級(jí)別、超時(shí)時(shí)間、是否為只讀事務(wù)和事務(wù)傳播規(guī)則
- PlatformTransactionManager:事務(wù)管理器,包含
commit
、rollback
、getTransaction
三個(gè)方法
根據(jù)上面的分析,我們知道TransactionInterceptor
本質(zhì)就是一個(gè)MethodInterceptor
,被事務(wù)攔截的方法最終都會(huì)執(zhí)行到此增強(qiáng)器身上。 MethodInterceptor
是個(gè)環(huán)繞通知,敲好符合我們的開啟、提交、回滾事務(wù)等操作。
3.1、invoke方法
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable { /** * Create a new TransactionInterceptor. * <p>Transaction manager and transaction attributes still need to be set. * @see #setTransactionManager * @see #setTransactionAttributes(java.util.Properties) * @see #setTransactionAttributeSource(TransactionAttributeSource) */ public TransactionInterceptor() { } /** * Create a new TransactionInterceptor. * @param ptm the default transaction manager to perform the actual transaction management * @param attributes the transaction attributes in properties format * @see #setTransactionManager * @see #setTransactionAttributes(java.util.Properties) */ public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) { setTransactionManager(ptm); setTransactionAttributes(attributes); } /** * Create a new TransactionInterceptor. * @param ptm the default transaction manager to perform the actual transaction management * @param tas the attribute source to be used to find transaction attributes * @see #setTransactionManager * @see #setTransactionAttributeSource(TransactionAttributeSource) */ public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) { setTransactionManager(ptm); setTransactionAttributeSource(tas); } @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); } //--------------------------------------------------------------------- // Serialization support //--------------------------------------------------------------------- private void writeObject(ObjectOutputStream oos) throws IOException { // Rely on default serialization, although this class itself doesn't carry state anyway... oos.defaultWriteObject(); // Deserialize superclass fields. oos.writeObject(getTransactionManagerBeanName()); oos.writeObject(getTransactionManager()); oos.writeObject(getTransactionAttributeSource()); oos.writeObject(getBeanFactory()); } private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { // Rely on default serialization, although this class itself doesn't carry state anyway... ois.defaultReadObject(); // Serialize all relevant superclass fields. // Superclass can't implement Serializable because it also serves as base class // for AspectJ aspects (which are not allowed to implement Serializable)! setTransactionManagerBeanName((String) ois.readObject()); setTransactionManager((PlatformTransactionManager) ois.readObject()); setTransactionAttributeSource((TransactionAttributeSource) ois.readObject()); setBeanFactory((BeanFactory) ois.readObject()); } }
其中invoke調(diào)用父類TransactionAspectSupport的invokeWithinTransaction方法
3.2、invokeWithinTransaction方法
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean { /** * 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. * @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 (this.reactiveAdapterRegistry != null) { if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) { throw new TransactionUsageException("Unsupported annotated transaction on suspending function detected: " + method + ". Use TransactionalOperator.transactional extensions instead."); } ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType()); if (adapter != null) { return new ReactiveTransactionSupport(adapter).invokeWithinTransaction(method, targetClass, invocation); } } //獲取事務(wù)屬性源 TransactionAttributeSource tas = getTransactionAttributeSource(); //獲取方法對(duì)應(yīng)的事務(wù)屬性 final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); //找到合適事務(wù)管理器 final PlatformTransactionManager tm = determineTransactionManager(txAttr); //獲取方法的唯一標(biāo)識(shí) final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); // 如果txAttr為空或者tm屬于非CallbackPreferringPlatformTransactionManager,執(zhí)行目標(biāo)增強(qiáng) // 在TransactionManager上,CallbackPreferringPlatformTransactionManager實(shí)現(xiàn)PlatformTransactionManager接口,暴露出一個(gè)方法用于執(zhí)行事務(wù)處理中的回調(diào) if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { //看是否有必要?jiǎng)?chuàng)建一個(gè)事務(wù),根據(jù)事務(wù)傳播行為做出相應(yīng)的判斷 TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal; try { //回調(diào)方法執(zhí)行,執(zhí)行目標(biāo)方法(原有的業(yè)務(wù)邏輯) retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { // 出現(xiàn)異常了,進(jìn)行回滾(注意:并不是所有異常都會(huì)rollback的) //如果出現(xiàn)的異常不需要rollback,則會(huì)進(jìn)行commit completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { //清除信息 cleanupTransactionInfo(txInfo); } if (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); } } // 目標(biāo)方法完全執(zhí)行完成后,提交事務(wù) commitTransactionAfterReturning(txInfo); return retVal; } //編程式事務(wù)處理(CallbackPreferringPlatformTransactionManager) 會(huì)走這里 else { final ThrowableHolder throwableHolder = new ThrowableHolder(); // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in. try { Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> { TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); try { Object retVal = invocation.proceedWithInvocation(); if (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); } }); // Check result state: It might indicate a Throwable to rethrow. if (throwableHolder.throwable != null) { throw throwableHolder.throwable; } return result; } 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; } } } }
邏輯很清晰,本質(zhì)就是通過try…catch…進(jìn)行事務(wù)的提交或者回滾。我們看下里面的獲取事務(wù)管理器的方法determineTransactionManager
3.3、determineTransactionManager方法
@Nullable protected PlatformTransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) { //如果這兩個(gè)都沒配置,所以肯定是手動(dòng)設(shè)置了PlatformTransactionManager的,那就直接返回即可 if (txAttr == null || this.beanFactory == null) { return asPlatformTransactionManager(getTransactionManager()); } //qualifier相當(dāng)于beanName String qualifier = txAttr.getQualifier(); if (StringUtils.hasText(qualifier)) { //根據(jù)此名稱以及PlatformTransactionManager.class 去容器內(nèi)找bean return determineQualifiedTransactionManager(this.beanFactory, qualifier); } // 若沒有指定qualifier,那再看看是否指定了transactionManagerBeanName else if (StringUtils.hasText(this.transactionManagerBeanName)) { return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName); } //如果都沒指定,那就不管了。直接根據(jù)類型去容器里找 getBean(Class) //注:如果容器里面有多個(gè)PlatformTransactionManager,那么就會(huì)導(dǎo)致報(bào)錯(cuò) else { PlatformTransactionManager defaultTransactionManager = asPlatformTransactionManager(getTransactionManager()); if (defaultTransactionManager == null) { defaultTransactionManager = asPlatformTransactionManager( this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY)); if (defaultTransactionManager == null) { defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class); this.transactionManagerCache.putIfAbsent( DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager); } } return defaultTransactionManager; } }
3.4、createTransactionIfNecessary
再看下創(chuàng)建事務(wù)的方法createTransactionIfNecessary,在看方法前,我們先看下返回的TransactionInfo類
protected static final class TransactionInfo { // 當(dāng)前事務(wù)的事務(wù)管理器 @Nullable private final PlatformTransactionManager transactionManager; // 當(dāng)前事務(wù)的事務(wù)屬性 @Nullable private final TransactionAttribute transactionAttribute; //joinpoint標(biāo)識(shí) private final String joinpointIdentification; // 當(dāng)前事務(wù)的TransactionStatus @Nullable private TransactionStatus transactionStatus; //保存當(dāng)前事務(wù)所在的父事務(wù)上下文的引用,構(gòu)成了一個(gè)鏈,準(zhǔn)確的說是一個(gè)有向無環(huán)圖 @Nullable private TransactionInfo oldTransactionInfo; public TransactionInfo(@Nullable PlatformTransactionManager transactionManager, @Nullable TransactionAttribute transactionAttribute, String joinpointIdentification) { this.transactionManager = transactionManager; this.transactionAttribute = transactionAttribute; this.joinpointIdentification = joinpointIdentification; } public PlatformTransactionManager getTransactionManager() { Assert.state(this.transactionManager != null, "No PlatformTransactionManager set"); return this.transactionManager; } @Nullable public TransactionAttribute getTransactionAttribute() { return this.transactionAttribute; } /** * Return a String representation of this joinpoint (usually a Method call) * for use in logging. */ public String getJoinpointIdentification() { return this.joinpointIdentification; } //創(chuàng)建一個(gè)新的事務(wù) public void newTransactionStatus(@Nullable TransactionStatus status) { this.transactionStatus = status; } @Nullable public TransactionStatus getTransactionStatus() { return this.transactionStatus; } /** * Return whether a transaction was created by this aspect, * or whether we just have a placeholder to keep ThreadLocal stack integrity. */ public boolean hasTransaction() { return (this.transactionStatus != null); } //綁定當(dāng)前正在處理的事務(wù)的所有信息到ThreadLocal private void bindToThread() { // Expose current TransactionStatus, preserving any existing TransactionStatus // for restoration after this transaction is complete. //先從線程中拿出來老的,再把新的(也就是當(dāng)前)綁定進(jìn)去 this.oldTransactionInfo = transactionInfoHolder.get(); transactionInfoHolder.set(this); } //當(dāng)前事務(wù)處理完之后,恢復(fù)父事務(wù)上下文 private void restoreThreadLocalStatus() { // Use stack to restore old transaction TransactionInfo. // Will be null if none was set. transactionInfoHolder.set(this.oldTransactionInfo); } @Override public String toString() { return (this.transactionAttribute != null ? this.transactionAttribute.toString() : "No transaction"); } }
然后再看創(chuàng)建事務(wù)的方法createTransactionIfNecessary
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; } }; } //從事務(wù)管理器里,通過txAttr拿出來一個(gè)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"); } } } //通過TransactionStatus 等,轉(zhuǎn)換成一個(gè)通用的TransactionInfo return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); }
再看方法prepareTransactionInfo
protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, String joinpointIdentification, @Nullable TransactionStatus status) { //構(gòu)造一個(gè)TransactionInfo 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. //把生成的TransactionInfo并綁定到當(dāng)前線程的ThreadLocal txInfo.bindToThread(); return txInfo; }
3.5、commitTransactionAfterReturning
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) { if (txInfo != null && txInfo.getTransactionStatus() != null) { if (logger.isTraceEnabled()) { logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]"); } //直接使用事務(wù)管理器提交事務(wù) txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } }
3.6、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); } //如果有事務(wù)屬性了,那就調(diào)用rollbackOn看看這個(gè)異常需不需要回滾 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; } } } }
3.7、cleanupTransactionInfo
protected void cleanupTransactionInfo(@Nullable TransactionInfo txInfo) { if (txInfo != null) { //清除(解綁)事務(wù) txInfo.restoreThreadLocalStatus(); } }
4、PlatformTransactionManager
事務(wù)管理器接口
public interface PlatformTransactionManager extends TransactionManager { //創(chuàng)建事務(wù) TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException; //提交事務(wù) void commit(TransactionStatus status) throws TransactionException; //回滾事務(wù) void rollback(TransactionStatus status) throws TransactionException; }
4.1、AbstractPlatformTransactionManager
是對(duì)PlatformTransactionManager
的一個(gè)抽象實(shí)現(xiàn),這個(gè)基類提供了以下工作流程處理
- 確定如果有現(xiàn)有的事務(wù);
- 應(yīng)用適當(dāng)?shù)膫鞑バ袨?
- 如果有必要暫停和恢復(fù)事務(wù);
- 提交時(shí)檢查rollback-only標(biāo)記;
- 應(yīng)用適當(dāng)?shù)男薷漠?dāng)回滾(實(shí)際回滾或設(shè)置rollback-only);
- 觸發(fā)同步回調(diào)注冊(cè)(如果事務(wù)同步是激活的)
(1)getTransaction方法
@Override public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException { //如果沒有配置事務(wù)屬性,則使用默認(rèn)的事務(wù)屬性 TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults()); //獲取事務(wù),具體的實(shí)現(xiàn)由具體的事務(wù)處理器提供 Object transaction = doGetTransaction(); boolean debugEnabled = logger.isDebugEnabled(); //檢查當(dāng)前線程是否存在事務(wù),如果是則直接處理已存在的事務(wù),isExistingTransaction方法由子類去實(shí)現(xiàn) if (isExistingTransaction(transaction)) { // Existing transaction found -> check propagation behavior to find out how to behave. return handleExistingTransaction(def, transaction, debugEnabled); } //超時(shí)時(shí)間的校驗(yàn) if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout()); } //處理事務(wù)屬性中配置的事務(wù)傳播特性 // PROPAGATION_MANDATORY 如果已經(jīng)存在一個(gè)事務(wù),支持當(dāng)前事務(wù)。如果沒有一個(gè)活動(dòng)的事務(wù),則拋出異常 if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'"); } //如果事務(wù)傳播特性為required、required_new或nested else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { // 掛起,doSuspend()由子類去實(shí)現(xiàn) // 掛起操作,觸發(fā)相關(guān)的掛起注冊(cè)的事件,把當(dāng)前線程事物的所有屬性都封裝好,放到一個(gè)SuspendedResourcesHolder // 然后清空清空一下當(dāng)前線程事務(wù) SuspendedResourcesHolder suspendedResources = suspend(null); if (debugEnabled) { logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def); } //此處,開始創(chuàng)建事務(wù) try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); //創(chuàng)建一個(gè)新的事務(wù)狀態(tài) 就是new DefaultTransactionStatus() 把個(gè)屬性都賦值上 DefaultTransactionStatus status = newTransactionStatus( def, transaction, true, newSynchronization, debugEnabled, suspendedResources); //開始事務(wù),抽象方法,由子類去實(shí)現(xiàn)~ doBegin(transaction, def); //初始化和同步事務(wù)狀態(tài) prepareSynchronization(status, def); return status; } catch (RuntimeException | Error ex) { //重新開始 doResume由子類去實(shí)現(xiàn) resume(null, suspendedResources); throw ex; } } // 走到這里表示傳播屬性就是不需要事務(wù)的,直接創(chuàng)建一個(gè) 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); } }
(2)commit方法
@Override public final void commit(TransactionStatus status) throws TransactionException { //如果是一個(gè)已經(jīng)完成的事物,不可重復(fù)提交 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; // 如果已經(jīng)標(biāo)記為了需要回滾,那就執(zhí)行回滾吧 if (defStatus.isLocalRollbackOnly()) { if (defStatus.isDebug()) { logger.debug("Transactional code has requested rollback"); } processRollback(defStatus, false); return; } // shouldCommitOnGlobalRollbackOnly這個(gè)默認(rèn)值是false,目前只有JTA事務(wù)復(fù)寫成true了 // isGlobalRollbackOnly:是否標(biāo)記為了全局的RollbackOnly 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; } // 提交事務(wù),會(huì)考慮到還原點(diǎn)、新事務(wù)、事務(wù)是否是rollback-only之類的 processCommit(defStatus); }
(3)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; //交給子類去實(shí)現(xiàn) processRollback(defStatus, false); }
4.2、DataSourceTransactionManager
以最為常用DataSourceTransactionManager
作為實(shí)現(xiàn)類看看內(nèi)部具體如何實(shí)現(xiàn)
(1)doGetTransaction
@Override protected Object doGetTransaction() { DataSourceTransactionObject txObject = new DataSourceTransactionObject(); txObject.setSavepointAllowed(isNestedTransactionAllowed()); ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource()); txObject.setConnectionHolder(conHolder, false); return txObject; }
(2)doBegin
@Override protected void doBegin(Object transaction, TransactionDefinition definition) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; Connection con = null; try { if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) { //從DataSource里獲取一個(gè)連接(這個(gè)DataSource一般是有連接池的) Connection newCon = obtainDataSource().getConnection(); if (logger.isDebugEnabled()) { logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction"); } // 把這個(gè)連接用ConnectionHolder包裝一下 txObject.setConnectionHolder(new ConnectionHolder(newCon), true); } txObject.getConnectionHolder().setSynchronizedWithTransaction(true); con = txObject.getConnectionHolder().getConnection(); // 設(shè)置isReadOnly、設(shè)置隔離界別等 Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); //這里非常的關(guān)鍵,先看看Connection 是否是自動(dòng)提交的 //如果是 就con.setAutoCommit(false) 要不然數(shù)據(jù)庫默認(rèn)沒執(zhí)行一條SQL都是一個(gè)事務(wù),就沒法進(jìn)行事務(wù)的管理了 //因此從這后面,通過此Connection執(zhí)行的所有SQL語句只要沒有commit就都不會(huì)提交給數(shù)據(jù)庫的 if (con.getAutoCommit()) { txObject.setMustRestoreAutoCommit(true); if (logger.isDebugEnabled()) { logger.debug("Switching JDBC Connection [" + con + "] to manual commit"); } con.setAutoCommit(false); } //這個(gè)方法特別特別有意思 它自己`Statement stmt = con.createStatement()`拿到一個(gè)Statement // 然后執(zhí)行了一句SQL:`stmt.executeUpdate("SET TRANSACTION READ ONLY");` // 所以,所以:如果你僅僅只是查詢。把事務(wù)的屬性設(shè)置為readonly=true Spring對(duì)幫你對(duì)SQl進(jìn)行優(yōu)化的 // 需要注意的是:readonly=true 后,只能讀,不能進(jìn)行dml操作)(只能看到設(shè)置事物前數(shù)據(jù)的變化,看不到設(shè)置事物后數(shù)據(jù)的改變) prepareTransactionalConnection(con, definition); txObject.getConnectionHolder().setTransactionActive(true); int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getConnectionHolder().setTimeoutInSeconds(timeout); } // 這一步:就是把當(dāng)前的連接和當(dāng)前的線程進(jìn)行綁定 if (txObject.isNewConnectionHolder()) { TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder()); } } catch (Throwable ex) { //如果是新創(chuàng)建的連接,那就釋放 if (txObject.isNewConnectionHolder()) { DataSourceUtils.releaseConnection(con, obtainDataSource()); txObject.setConnectionHolder(null, false); } throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex); } }
(3)doCommit
@Override protected void doCommit(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); if (status.isDebug()) { logger.debug("Committing JDBC transaction on Connection [" + con + "]"); } try { con.commit(); } catch (SQLException ex) { throw new TransactionSystemException("Could not commit JDBC transaction", ex); } }
到此這篇關(guān)于Java中SpringBoot的@Transactional原理的文章就介紹到這了,更多相關(guān)SpringBoot的@Transactional原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中為什么this可以調(diào)用當(dāng)前實(shí)例
本文主要介紹了為什么可以通過this關(guān)鍵字訪問到當(dāng)前對(duì)象呢,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07MybatisPlus 多租戶架構(gòu)(Multi-tenancy)實(shí)現(xiàn)詳解
這篇文章主要介紹了MybatisPlus 多租戶架構(gòu)(Multi-tenancy)實(shí)現(xiàn)詳解,詳細(xì)的介紹了什么是多租戶架構(gòu)以及使用MybatisPlus實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-11-11SpringBoot啟動(dòng)報(bào)錯(cuò)屬性循環(huán)依賴報(bào)錯(cuò)問題的解決
這篇文章主要介紹了SpringBoot啟動(dòng)報(bào)錯(cuò)屬性循環(huán)依賴報(bào)錯(cuò)問題的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05java線程安全鎖ReentrantReadWriteLock原理分析readLock
這篇文章主要為大家介紹了java線程安全鎖ReentrantReadWriteLock原理分析readLock,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10mybatis中resultMap 標(biāo)簽的使用教程
resultMap 標(biāo)簽用來描述如何從數(shù)據(jù)庫結(jié)果集中來加載對(duì)象,這篇文章重點(diǎn)給大家介紹mybatis中resultMap 標(biāo)簽的使用,感興趣的朋友一起看看吧2018-07-07Springcloud中Feign傳遞參數(shù)的過程解析
這篇文章主要介紹了Springcloud中Feign傳遞參數(shù)的過程,單個(gè)參數(shù)的傳值有兩種方式,第一種使用@RequestParam/@PathVariable進(jìn)行傳值,傳遞多個(gè)參數(shù):多個(gè)參數(shù)的傳值可以使用多個(gè)@RequestParam來進(jìn)行傳參,需要的朋友可以參考下2023-09-09Java探索之Thread+IO文件的加密解密代碼實(shí)例
這篇文章主要介紹了Java探索之Thread+IO文件的加密解密代碼實(shí)例,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10