文章目录

  • 概述
  • 源码解析
    • xml 配置解析
    • 事务代理类的创建
    • 事务拦截器的实现
    • 切面实现
    • 事务处理实现
    • 总结:
  • 资料

概述

事务处理是一个重要并且涉及范围很广的领域,涉及到并发和数据一致性方面的问题。作为应用平台的 Spring 具有在多种环境中配置和使用事务处理的能力,也就是说通过使用 Spring 的事务处理,可以把事务处理的工作统一起来,为事务处理提供统一支持。

由于这方面的内容比较多,这里只讲事务处理中最为基本的使用场景,即 Spring 是怎样实现对单个数据库局部事务处理的。

在 Spring 中,既支持编程式事务管理方式,又支持声明式事务处理方式。编程式事务管理代码如下所示:

Connection conn = null;
UserTransaction tx = null;
try {tx = getUserTransaction();                       //1.获取事务tx.begin();                                    //2.开启JTA事务conn = getDataSource().getConnection();           //3.获取JDBC// 4.声明SQLString sql = "select * from INFORMATION_SCHEMA.SYSTEM_TABLES";PreparedStatement pstmt = conn.prepareStatement(sql);//5.预编译SQLResultSet rs = pstmt.executeQuery();               //6.执行SQLprocess(rs);                                   //7.处理结果集closeResultSet(rs);                             //8.释放结果集tx.commit();                                  //7.提交事务
} catch (Exception e) {tx.rollback();                                 //8.回滚事务throw e;
} finally {conn.close();                                //关闭连接
}

也就是把事务的开始、提交、回滚显式的写到了代码里。这种方式好处是灵活,缺点是啰嗦,对开发人员要求较高,稍有不慎就写出故障来了。

Spring 中的声明式事务处理是用户最常用的,通过将事务处理的过程和业务代码分离开来,大大简化了代码的编写。声明式事务有两种使用方式,第一种是纯粹的 xml 文件配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="  http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop-3.0.xsdhttp://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.0.xsd"><!-- 配置数据源 --><bean id="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver" /><property name="url" value="jdbc:mysql://localhost:3306/test" /><property name="username" value="root" /><property name="password" value="christmas258@" /></bean><!--配置一个JdbcTemplate实例,并将这个“共享的”,“安全的”实例注入到不同的DAO类中去 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource" /></bean><!-- 声明事务管理器 --><bean id="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><!-- 需要实施事务增强的目标业务Bean --><bean id="libraryTarget" class="com.mucfc.dao.LibraryDaoImpl"p:jdbcTemplate-ref="jdbcTemplate" /><!-- 使用事务代理工厂类为目标业务Bean提供事务增强 --><bean id="libraryFactory"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"p:transactionManager-ref="txManager" p:target-ref="libraryTarget"><!-- 事务属性配置 --><property name="transactionAttributes"><props><!-- 以get开头的方法采用只读型事务控制类型 --><prop key="get*">PROPAGATION_REQUIRED,readOnly</prop><!-- 所有方法均进行事务控制,如果当前没有事务,则新建一个事务 --><prop key="addBook">PROPAGATION_REQUIRED</prop></props></property></bean>
</beans>

在这里配置了数据源 dataSource、事务管理器 transactionManager、待事务增强的目标业务 Bean、事务增强配置。第二种是注解方式,不过 xml 中依然需要配置数据源 dataSource 和事务管理器 transactionManager,额外还需要加上 annotation-driven 配置。

@Transactional
public void run() {// DB 操作
}<tx:annotation-driven/>

源码解析

这里,我们以注解方式为例,讲一下声明式事务的实现原理。注解方式的声明式事务本质上是把编程式事务中原本需要用户自己写的代码进行了封装,并通过 AOP 的方式来生成了具体业务类的代理类。

xml 配置解析

无论是纯粹 xml 配置,还是注解加配置的方式,都需要 Spring 通过 TxNamespaceHandler 来解析事务标签,代码如下所示:

public class TxNamespaceHandler extends NamespaceHandlerSupport {static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";static String getTransactionManagerName(Element element) {return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);}@Overridepublic void init() {registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());}
}

从代码中可知,annotation-driven 标签是由 AnnotationDrivenBeanDefinitionParser 类来解析的。首先 tx:annotation-driven 有一个 model 属性,有两个值 proxy 和 aspectj。该类根据 xml 配置来决定加载哪些 AOP 相关类。

下面以 proxy 方式为例,说一下都加载了哪些类?

 private static class AopAutoProxyConfigurer {public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {// 注册 InfrastructureAdvisorAutoProxyCreator 类AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {Object eleSource = parserContext.extractSource(element);// 注册 AnnotationTransactionAttributeSource 类.RootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");sourceDef.setSource(eleSource);sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);// 注册 TransactionInterceptor 类.RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);interceptorDef.setSource(eleSource);interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registerTransactionManager(element, interceptorDef);interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);// 注册 TransactionAttributeSourceAdvisor 类.RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);advisorDef.setSource(eleSource);advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);if (element.hasAttribute("order")) {advisorDef.getPropertyValues().add("order", element.getAttribute("order"));}parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));parserContext.registerComponent(compositeDef);}}}

在这里注册了四个类:

  1. InfrastructureAdvisorAutoProxyCreator:实现了 BeanPostProcessor 接口,在 postProcessAfterInitialization 方法中会根据需要创建 Proxy 类。
  2. AnnotationTransactionAttributeSource:解析事务类,得到事务配置相关信息。
  3. TransactionInterceptor:事务拦截器,实现了 Advice、MethodInterceptor 接口。
  4. BeanFactoryTransactionAttributeSourceAdvisor:实现了 PointcutAdvisor 接口,依赖 TransactionInterceptor 和 TransactionAttributeSourcePointcut。

事务代理类的创建

Spring 在创建 bean 之后,会执行 BeanPostProcessor 的 postProcessAfterInitialization 方法。而 InfrastructureAdvisorAutoProxyCreator 继承了 AbstractAutoProxyCreator 类,AbstractAutoProxyCreator 实现了 BeanPostProcessor 接口:

 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.contains(cacheKey)) {return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// 查找适合此 bean 的 advisorObject[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);// 创建代理Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}

如何查找适合某个 bean 的 advisor 呢?可以看下面的代码:

 protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {// 查找适合此 bean 的 advisorList<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();}protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {List<Advisor> candidateAdvisors = findCandidateAdvisors();// 查找适合此 bean 的 advisorList<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {ProxyCreationContext.setCurrentProxiedBeanName(beanName);try {return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);} finally {ProxyCreationContext.setCurrentProxiedBeanName(null);}}public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {eligibleAdvisors.add(candidate);}}boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor) {continue;}if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {if (advisor instanceof IntroductionAdvisor) {return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);} else if (advisor instanceof PointcutAdvisor) {PointcutAdvisor pca = (PointcutAdvisor) advisor;return canApply(pca.getPointcut(), targetClass, hasIntroductions);} else {// It doesn't have a pointcut so we assume it applies.return true;}}public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {Assert.notNull(pc, "Pointcut must not be null");if (!pc.getClassFilter().matches(targetClass)) {return false;}MethodMatcher methodMatcher = pc.getMethodMatcher();if (methodMatcher == MethodMatcher.TRUE) {// No need to iterate the methods if we're matching any method anyway...return true;}IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;if (methodMatcher instanceof IntroductionAwareMethodMatcher) {introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;}Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));classes.add(targetClass);for (Class<?> clazz : classes) {Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);for (Method method : methods) {if ((introductionAwareMethodMatcher != null &&introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||methodMatcher.matches(method, targetClass)) {return true;}}}return false;}

看到最后,可以知道有两种方法可以判断:

  1. Pointcut.getMethodMatcher().matches();
  2. IntroductionAdvisor.getClassFilter().matches。

事务拦截器的实现

在前面提到过,注册了 BeanFactoryTransactionAttributeSourceAdvisor 类,该类实现了 PointcutAdvisor 接口,其中的切面 pointcut 便是通过 TransactionAttributeSourcePointcut 来实现的。TransactionAttributeSourcePointcut 的 matches 方法是根据能否可以从目标 bean 中得到 TransactionAttribute 来判断是否匹配的。

public interface PointcutAdvisor extends Advisor {Pointcut getPointcut();
}
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {private TransactionAttributeSource transactionAttributeSource;private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {@Overrideprotected TransactionAttributeSource getTransactionAttributeSource() {return transactionAttributeSource;}};
}
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {@Overridepublic boolean matches(Method method, Class<?> targetClass) {if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {return false;}TransactionAttributeSource tas = getTransactionAttributeSource();return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);}
}

TransactionAttributeSource 的实现类主要是 AnnotationTransactionAttributeSource,该类使用 SpringTransactionAnnotationParser 类解析注解 Transactional 得到 TransactionAttribute:

 // 在 SpringTransactionAnnotationParser 类中public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(element, Transactional.class);if (attributes != null) {return parseTransactionAnnotation(attributes);}else {return null;}}protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();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<RollbackRuleAttribute>();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;}

切面实现

前面讲了如何判断一个类是否需要创建事务处理的代理类,下面讲一下用于实现事务处理的切面实现。

TransactionInterceptor 实现了方法拦截器 MethodInterceptor 接口,用于对业务类进行事务增强。TransactionInterceptor 的 invoke 方法主要是调用了父类 TransactionAspectSupport 的 invokeWithinTransaction 方法。

 @Overridepublic Object invoke(final MethodInvocation invocation) throws Throwable {Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {@Overridepublic Object proceedWithInvocation() throws Throwable {return invocation.proceed();}});}protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) throws Throwable {// 获取事务配置信息final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);// 获取事务管理器final PlatformTransactionManager tm = determineTransactionManager(txAttr);final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);// 同步操作if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {// 创建事务类TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);Object retVal = null;try {// 环绕增强:触发链条上的下一个拦截器,最终会调用目标类retVal = invocation.proceedWithInvocation();} catch (Throwable ex) {// 出现异常则回滚completeTransactionAfterThrowing(txInfo, ex);throw ex;} finally {cleanupTransactionInfo(txInfo);}commitTransactionAfterReturning(txInfo);return retVal;} else {// 省略异步操作,原理类似}}

invoke 方法里主要做以下几件事:

  1. 获取事务属性;
  2. 获取事务管理器;
  3. 创建事务;
  4. 执行目标方法;
  5. 遇到异常则回滚,正常结束则提交。

事务处理实现

对于具体的事务处理实现,比如事务的生成、提交、回滚、挂起等,由于不同的底层数据库有不同的支持方式,因此在 Spring 事务处理中,对主要的事务实现做了一个抽象和适配。Spring 设计了 PlatformTransactionManager 接口,抽象出事务管理的主要功能:提交、回滚,并提供了针对不同数据源的实现:针对 DataSource 数据源的 DataSourceTransactionManager、针对 Hibernate 数据源的 HibernateTransactionManager、针对 JDO 数据源的 JdoTransactionManager 等等。

public interface PlatformTransactionManager {// 获取事务对象 TransactionStatus,如果没有就创建一个TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;// 提交void commit(TransactionStatus status) throws TransactionException;// 回滚void rollback(TransactionStatus status) throws TransactionException;
}

下面分析一下最常见的 DataSourceTransactionManager,该类继承自 AbstractPlatformTransactionManager,AbstractPlatformTransactionManager 实现了 PlatformTransactionManager 接口,

 @Overrideprotected void doCommit(DefaultTransactionStatus status) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();Connection con = txObject.getConnectionHolder().getConnection();try {con.commit();} catch (SQLException ex) {throw new TransactionSystemException("Could not commit JDBC transaction", ex);}}@Overrideprotected void doRollback(DefaultTransactionStatus status) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();Connection con = txObject.getConnectionHolder().getConnection();try {con.rollback();} catch (SQLException ex) {throw new TransactionSystemException("Could not roll back JDBC transaction", ex);}}

提交和回滚都比较简单,主要是调用了 Connection 的对应类。下面我们详细看一下 getTransaction 的实现:

 public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {// 获取事务(如果当前已经存在的话)Object transaction = doGetTransaction();if (definition == null) {// Use defaults if no transaction definition given.definition = new DefaultTransactionDefinition();}// 如果当前线程已经存在事务,需要特殊处理if (isExistingTransaction(transaction)) {return handleExistingTransaction(definition, transaction, debugEnabled);}// PROPAGATION_MANDATORY 表示支持当前事务,如果当前没有事务,就抛出异常。if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {throw new IllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'");} else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {SuspendedResourcesHolder suspendedResources = suspend(null);try {// 创建新事务boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);doBegin(transaction, definition);prepareSynchronization(status, definition);return status;} catch (RuntimeException ex) {resume(null, suspendedResources);throw ex;} catch (Error err) {resume(null, suspendedResources);throw err;}} else {// 创建空事务boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);}}// 当事务已经存在时,处理最为复杂private TransactionStatus handleExistingTransaction(TransactionDefinition definition, Object transaction, boolean debugEnabled)throws TransactionException {// PROPAGATION_NEVER 表示必须以非事务方式运行,如果已经存在事务,则抛出异常if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {throw new IllegalTransactionStateException("Existing transaction found for transaction marked with propagation 'never'");}// PROPAGATION_NOT_SUPPORTED 表示以非事务方式执行操作,如果当前存在事务,就把当前事务挂起if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {Object suspendedResources = suspend(transaction);boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);return prepareTransactionStatus(definition, null, false, newSynchronization, debugEnabled, suspendedResources);}// PROPAGATION_REQUIRES_NEW 表示新建事务,如果当前存在事务,把当前事务挂起if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {SuspendedResourcesHolder suspendedResources = suspend(transaction);try {boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);doBegin(transaction, definition);prepareSynchronization(status, definition);return status;} catch (RuntimeException beginEx) {resumeAfterBeginException(transaction, suspendedResources, beginEx);throw beginEx;} catch (Error beginErr) {resumeAfterBeginException(transaction, suspendedResources, beginErr);throw beginErr;}}// PROPAGATION_NESTED 表示如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作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 (useSavepointForNestedTransaction()) {// 如果支持 Savepoint,则创建 SavepointDefaultTransactionStatus status =prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);status.createAndHoldSavepoint();return status;} else {// 创建新事务boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);doBegin(transaction, definition);prepareSynchronization(status, definition);return status;}}// 合法性校验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");}}}boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);}

总结:

Spring 事务处理模块主要类之间的关系如下图所示:

资料

  1. spring事物的七种事物传播属性行为及五种隔离级别
  2. Spring 技术内幕

【笔记】Spring 事务原理分析和源码剖析相关推荐

  1. Spring事务原理分析-部分一

    Spring事务原理分析-部分一 什么事务 事务:逻辑上的一组操作,组成这组操作的各个单元,要么全都成功,要么全都失败. 事务基本特性 ⑴ 原子性(Atomicity) 原子性是指事务包含的所有操作要 ...

  2. Spring事务原理分析(一)--@EnableTransactionManagement 到底做了什么?

    目录 一.概述 二.事务的ACID属性 三.事务的隔离级别 四.事务的传播行为 五.Spring声明式事务环境搭建 六.@EnableTransactionManagement分析 七.AutoPro ...

  3. 夯实Java基础系列3:一文搞懂String常见面试题,从基础到实战,更有原理分析和源码解析!

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  4. string 包含_一文搞懂String常见面试题,从基础到实战,到原理分析和源码解析...

    01 string基础 1.1 Java String 类 字符串广泛应用 在 Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串. 1.2 创建字 ...

  5. unity物理射线之原理分析(擅码网学习笔记)

    @[TOC]unity物理射线之原理分析(擅码网学习笔记) using System.Collections; using System.Collections.Generic; using Unit ...

  6. 【Mybatis+spring整合源码探秘】--- mybatis整合spring事务原理

    文章目录 1 mybatis整合spring事务原理 1 mybatis整合spring事务原理 本篇文章不再对源码进行具体的解读了,仅仅做了下面一张图: 该图整理了spring+mybatis整合后 ...

  7. 不同类的方法 事务问题_深入理解 Spring 事务原理

    Spring事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的.对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行: 获 ...

  8. 解析并符号 读取dll_Spring IOC容器之XmlBeanFactory启动流程分析和源码解析

    一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...

  9. Spring 事务管理高级应用难点剖析

    Spring 事务管理高级应用难点剖析: 第 1 部分 http://www.ibm.com/developerworks/cn/java/j-lo-spring-ts1/index.html htt ...

最新文章

  1. 学习笔记——sklearn监督学习:回归(简单数学知识罗列)
  2. 如何设置Flutter
  3. tomcat 设置虚拟路径
  4. 前端趋势榜:上周最有意思、又实用的 10 大 Web 项目 - 210821
  5. DELPHI跨平台的临界替代者
  6. MongoDB数据库查询性能提高40倍
  7. php7数据库备份还原,基于thinkphp的数据库在线备份还原
  8. 7-14 求整数段和 (15 分)
  9. 创业几乎不要本钱,是创业圈内最大的谎言
  10. initrd.img处理
  11. java匹配字符串所在位置_Java:获取字符串中匹配项位置的方法?
  12. 事务失败返回_分布式事务方案 TCC
  13. 搭建一个简单的SpringBoot项目
  14. 魔兽怀旧服服务器怎么修改,魔兽世界怀旧服今日开服 魔兽世界怀旧服剥皮制皮玩法攻略 怀旧服服务器连不上怎么办?...
  15. 如何下载和安装 iOS开发教程
  16. Intel SGX开发者参考书(一)——Intel SGX引言
  17. 半导体封装测试英语词汇量的软件,半导体英语
  18. Dota数据集切割以及保存为yolo和voc格式——HBB
  19. 机器学习之置信区间上界算法
  20. php fetch_assoc,PHP使用fetch_assoc()获取查询结果时数据类型都变了

热门文章

  1. 内网渗透—红日靶场三
  2. python多重背包_【动态规划】多重背包问题
  3. Android 从app中调起小程序(必成)!!!
  4. C语言100行代码实现推箱子
  5. 夜游项目如何深入挖掘文化特色城镇
  6. 录音读写程序c语言,如果用c语言程序读取一段音频文件要如何做,具体要调用哪些函数,在网上搜索了半天,乱七八糟的,找不到什么有用的信息...
  7. OpenWrt 学习笔记【6】配置USB驱动
  8. 是谁在我的心里打了个结(二十七)责任 【结局】
  9. ubuntu任务栏不见了
  10. 数据口径_如何使用口径组织您的电子书收藏