spring4.0事务超详细源码解析

Posted 看写写

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring4.0事务超详细源码解析相关的知识,希望对你有一定的参考价值。

事务

github:https://github.com/Notelzg/spring-reader
目前事务都是基于mysql的事务,其特性是 atomicity(原子性), consistency(一致性), isolation(隔离性), durability(持久性)
ACID四大特性。spring的事务就是在spring中对事务进行适配,通过模板的设计模式来避免 重复的代码,把重复性的开始事务、关闭事务、回滚等重复事情做了,而业务侧值只需要写业务代码
通过注解的方式开启事务就好了。这种方式提高了开发的效率,对事务进行代理对开发透明。 对后续的扩展比较方便。而且如果模板方法有问题,可以统一升级,而且避免了个人写事务导致的错误。
看到这里大家肯定会想到了spring的AOP,像这种重复的,有固定入口的,特别适合切面来做。spring 事务 也是实现了事务的切面增强,基于Spring AOP技术。

开启配置

在配置文件中,通过下面的配置开启对事务的支持。 这个如果你没有开启AOP的配置,这里会默认注册AOP,因为事务是基于AOP做的。

 //proxy-target-class 这里是tru,由于基于AOP所以这里指的是AOP的属性,是适应CgLib,还是JDK动态代理
 // 为true标识,代理类使用CgLib生成子类进行代理。如果Spring AOP还没有配置,这里会先注册AOP的 beanPost
 <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
  // 这里的false不会生效, 下面不会覆盖上面的(因为false不进行处理,true的时候属性设置为true,上面
  //这里是存在冲突的,请注意,可能导致事务失效,
 <aop:aspectj-autoproxy proxy-target-class="false"/>

配置激活的beanPost

1, xml命名空间和java类之间的映射 TxNamespaceHandler这个命名空间都是通过配置文件配置的, spring会加载所有的命名空间

spring-tx-4.3.30.RELEASE.jar/META-INF/spring.handlers
文件内容:
http\\://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler

2, java事务命名空间解析

public class TxNamespaceHandler extends NamespaceHandlerSupport 
  static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";
  static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";

  public void init() 
    this.registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
     // 上面配置的属性: annotation-driven  这个激活了这个配置
    this.registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
    this.registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
  

3, 注册事务需要用到的切面 AnnotationDrivenBeanDefinitionParser.java
xml文件解析, annotation-driven

public BeanDefinition parse(Element element, ParserContext parserContext) 
    this.registerTransactionalEventListenerFactory(parserContext);
    String mode = element.getAttribute("mode");
    // 这个应该是使用aspectJ的支持,目前我们都没有使用
    if ("aspectj".equals(mode)) 
    this.registerTransactionAspect(element, parserContext);
     else 
    // 正常情况下都走的这里
    AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);

注册 advice, pointCut, 织入 需要的类

// 专门定义了一个内部类来专门处理AOP相关的,也体现了设计模式的开闭原则
private static class AopAutoProxyConfigurer 
    private AopAutoProxyConfigurer() 
    

    public static void configureAutoProxyCreator(Element element, ParserContext parserContext) 
      AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
      String txAdvisorBeanName = "org.springframework.transaction.config.internalTransactionAdvisor";
      if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) 
        // 对spring 事务注解进行解析, 获取方法/类上面的事务属性,在TransactionAttributeSourcePointcut的时候使用
        Object eleSource = parserContext.extractSource(element);
        RootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
        sourceDef.setSource(eleSource);
        sourceDef.setRole(2);
        String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
        
        // 事务增强器,实现了advice 
        RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
        interceptorDef.setSource(eleSource);
        interceptorDef.setRole(2);
        // 这里设置 transctionManager 类名称, 这里新增属性,key:transactionManagerBeanName, 
        //value: transactionManager(配置文件里面配置的,transaction-manager:)
        AnnotationDrivenBeanDefinitionParser.registerTransactionManager(element, interceptorDef);
        // 设置解析事务注解类,这里就可以看出把pointCut 和 事务解析 分离的好处了 
        interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
        String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
        
        // advisor,里面包含了 advice 和 pointCut
        RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
        advisorDef.setSource(eleSource);
        advisorDef.setRole(2);
        // 把事务解析器注入, 这里是RuntimeBeanReference类型, 初始化bean的时候就会去生成该bean的对象
        // 这里是因为该类在pointCut静态检查的时候就需要使用,所以先进行初始化
        advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
        // 把事务增强器注入, 这里是字符串类型,为什么呢,初始化bean的时候不会获取增强器的bean的对象?
        // 这里设置成string,是为了延迟初始化增强器,因为增强器是在生成具体的代理的时候才需要生成,并且使用,
        // 所以可以延迟加载生成对象,这里也符合spring的哲学,能延迟加载的就延迟加载
        // 这里设置拦截器的名称 ,然后通过 父类的getAdvice()方法去获取具体对象
        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);
      

    
  

advisor

org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor
该类聚合了切点,和增强器,所以从这里开始分析,由于其实现了Advisor接口
所以BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans
所以BeanFactoryAdvisorRetrievalHelper是在AOP里面自动开启的,具体细节可以看AOP解析。
AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean 检查该类实现的所有接口,包含该类
检查所有方法,是否需要进行增强。
可以获取到事务的切面。

// 继承了 AbstractBeanFactoryPointcutAdvisor 有默认实现 getAdvice,只要设置adviceBeanName即可
// 在注册bena的时候,已经设置了adviceBeanName, 其类是:TransactionInterceptor.java
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor 

	private TransactionAttributeSource transactionAttributeSource;

    //切点,这个类是一个abstract, getTransactionAttributeSource 是子类实现,提供具体的解析,
    // TransactionAttributeSourcePointcut 提供整体的流程处理, 可以看做是一个模板类,处理统一的流程
	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() 
		@Override
		protected TransactionAttributeSource getTransactionAttributeSource() 
			return transactionAttributeSource;
		
	;


	/**
	 * Set the transaction attribute source which is used to find transaction
	 * attributes. This should usually be identical to the source reference
	 * set on the transaction interceptor itself.
	 * @see TransactionInterceptor#setTransactionAttributeSource
	 */
	public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) 
		this.transactionAttributeSource = transactionAttributeSource;
	

	/**
	 * Set the @link ClassFilter to use for this pointcut.
	 * Default is @link ClassFilter#TRUE.
	 */
	public void setClassFilter(ClassFilter classFilter) 
		this.pointcut.setClassFilter(classFilter);
	

    // 获取切点, 对类,方法
	@Override
	public Pointcut getPointcut() 
		return this.pointcut;
	



切点

org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable 
    // 个人任务这里包装一层,把pointCut和 TransactionAttributeSource解析组合起来,方便后续的扩展, 同时也是
   // 降低了耦合度,复杂度,方便维护和扩展
	@Override
	public boolean matches(Method method, Class<?> targetClass) 
		if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) 
			return false;
		
		// 子类实现该方法, 通过 AopAutoProxyConfigurer类,我们知道这里的source是
        // org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
		TransactionAttributeSource tas = getTransactionAttributeSource();
		// 改属性正常情况下都不能为空,如果为空有问题了,事务属性解析不为空,则标识是事务,需要增强
		return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
	
    // 子类实现这个方法,提供具体的注解解析实现,
	protected abstract TransactionAttributeSource getTransactionAttributeSource();


事务解析的整体流程

抽象父类,处理整理流程
Fallback 为什么有FallBack是因为解析属性的时候,会有很多倒退的操作
来保证能处理大部分的情况。

public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource 
    // 获取事务的属性
	@Override
	public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) 
	    // object类肯定不是,直接结束
		if (method.getDeclaringClass() == Object.class) 
			return null;
		

		// First, see if we have a cached value.
		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.
			if (cached == NULL_TRANSACTION_ATTRIBUTE) 
				return null;
			
			else 
				return cached;
			
		
		else 
			// 解析细节
			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) txAttr).setDescriptor(methodIdentification);
				
				if (logger.isDebugEnabled()) 
					logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
				
				this.attributeCache.put(cacheKey, txAttr);
			
			return txAttr;
		
	

	
	protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) 
		// 公共方法检查,非公共方法直接结束
		if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) 
			return null;
		

        // 如果是cglib生成的代理,则获取其父类
		Class<?> userClass = ClassUtils.getUserClass(targetClass);
		// 如果method 是来自接口的,则返回 userClass中的method,返回实现类中的method
		Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
		// If we are dealing with method with generic parameters, find the original method.
		specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);

		// First try is the method in the target class.
		// 调用子类的具体实现,这里是子类进行扩展, 比如对TranactionL 注解的解析,如果方法上解析成功,直接返回
		TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
		if (txAttr != null) 
			return txAttr;
		

		// Second try is the transaction attribute on the target class.
		// 方法上面没有,则进行类上面检查,同样是子类实现,比如注解解析
		txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
		if (txAttr != null && ClassUtils.isUserLevelMethod(method)) 
			return txAttr;
		

        // 倒退操作,尽可能的把事务解析出来
		if (specificMethod != method) 
			// Fallback is to look at the original method.
			txAttr = findTransactionAttribute(method);
			if (txAttr != null) 
				return txAttr;
			
			// Last fallback is the class of the original method.
			txAttr = findTransactionAttribute(method.getDeclaringClass());
			if (txAttr != null && ClassUtils.isUserLevelMethod(method)) 
				return txAttr;
			
		

		return null;
	

	protected abstract TransactionAttribute findTransactionAttribute(Class<?> clazz);
	protected abstract TransactionAttribute findTransactionAttribute(Method method);
	protected boolean allowPublicMethodsOnly()  return false; 

事务注解解析入口

org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
这里的具体解析是通过父类(AbstractFallbackTransactionAttributeSource)进行的,该类实现了父类的方法,进行扩展

// 注解解析类,继承一个抽象模板类,这个也是属于sprig的特色了,把统一处理的流程放在抽象类中,把经常变动/扩展的部分作为
// 抽象方法进行(封装变化), 达到开闭原则
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource implements Serializable 
  // 只支持 public方法上面的 事务注解
  private final boolean publicMethodsOnly;
  // 注解解析类
  private final Set<TransactionAnnotationParser> annotationParsers;

  public AnnotationTransactionAttributeSource() 
    this(true);
  

  public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) 
    this.publicMethodsOnly = publicMethodsOnly;
    this.annotationParsers = new LinkedHashSet(4);
    // 默认支持 spring 事务解析, 目前事务注解都是走的这里
    this.annotationParsers.add(new SpringTransactionAnnotationParser());
  

  protected TransactionAttribute findTransactionAttribute(Class<?> clazz) 
    return this.determineTransactionAttribute(clazz);
  

  // 这两个方法 返回值、方法名称一样,入参不一样,属于静态的多态
  protected TransactionAttribute findTransactionAttribute(Method method) 
    return this.determineTransactionAttribute(method);
  
  
  // 解析类、方法上面的注解
  protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) 
    if (element.getAnnotations().length > 0) 
      // 解析的类可能存在多个,所以是循环
      Iterator var2 = this.annotationParsers.iterator();

      while(var2.hasNext()) 
        TransactionAnnotationParser annotationParser = (TransactionAnnotationParser)var2.next();
        // 开始机械
        TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
        // 解析就快速结束
        if (attr != null) 
          return attr;
        
      
    

    return null;
  

  protected boolean allowPublicMethodsOnly() 
    return this.publicMethodsOnly;
  



事务注解解析器

一个接口,一个实现类,面向接口编程
比较符合先设计,再实现。spring这个模式非常的好。但是工作中有的时候很难做到
这种方法确实是和扩展。同时发现spring中类名起的都很好,形容词 名称 动词
每次自己起名字是真的难

public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable 

	@Override
	public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) 
	   // 获取事务注解的所有属性
		AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(
				element, Transactional.class);
		// 解析		
		if (attributes != null) 
			return parseTransactionAnnotation(attributes);
		
		else 
			return null;
		
	

    // 从这里就可以知道,spring 事务注解支持哪些配置
	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;
	


增强器

package org.springframework.transaction.interceptor;
TransactionInterceptor.java
就是具体的事务增强器

增强器对象的获取


package org.springframework.aop.support;
public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware 

	private String adviceBeanName;

	// transient 序列化的时候,不进行序列化
    // volatile 关键字是可见性,不加可以吗?
    // 其实这里可以不加这关键字,因为单例本身是做了检查的,可以保证对象只创建一次, 加上就可以不用每次都走单例的流程,
    // 在这里就可以直接解决了,加快是了速度,所以这里加这个关键字主要是为了单例对象使用(大部分都是单例)
    // 而原始对象由于初始化的是有 synchronized关键字,所以可以保证其有序性、原子性
	private transient volatile Advice advice;
    // transient 序列化的时候,不进行序列化
    // 没有明白这里使用 volatile关键字的作用,由于这个对象会暴露出去,同时可以被重置,所以
    // 需要加上 volatile 关键字,保证其可见性
    private transient volatile Object adviceMonitor = new Object();

  // org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor
    // 继承了该类, 同时设置了adviceBeanName, TransactionInterceptor
	public void setAdviceBeanName(String adviceBeanName) 
		this.adviceBeanName = adviceBeanName;
	

	@Override
	public Advice getAdvice() 
	    // 单例,已经实例化的直接返回
		Advice advice = this.advice;
		if (advice != null || this.adviceBeanName == null) 
			return advice;
		

		Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");
		if (this.beanFactory.isSingleton(this.adviceBeanName)) 
			// 直接通过容器初始化增强器,由于增强器beanDefinition 在xml解析阶段已经注册,所以这里通过beanName可以完成bean的对象的
            // 初始化
			advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
			this.advice = advice;
			return advice;
		
		
		else 
			// No singleton guarantees from the factory -> let's lock locally but
			// reuse the factory's singleton lock, just in case a lazy dependency
			// of our advice bean happens to trigger the singleton lock implicitly...
          // 对于非单利的,也要进行单利处理,springAOP只能使用单利,因为如果使用非单例,将会生成n个对象
          // 对内存造成非常大的浪费,如果有1000个类,则要生成1000个对象,完成没有必要,所以切面本身要线程
          // 安全,因为切面通过锁巧妙的实现了单例
          synchronized (this.adviceMonitor) 
				if (this.advice == null) 
					this.advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
				
				return this.advice;
			
		
	


增强器对象的具体实现细节

这里是

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable 

	public TransactionInterceptor() 
	

	@Override
	public Object invoke(final 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);

		// 调用父类的方法, 通过回调方法,进行扩展
		return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() 
			@Override
			public Object proceedWithInvocation() throws Throwable 
				return invocation.proceed();
			
		);
	


事务操作整体流程

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean 
	/**
	 * Key to use to store the default transaction manager.
	 */
	private static final Object DEFAULT_TRANSACTION_MANAGER_KEY = new Object();

	// 事务信息,放到这里,进行方法调用的时候进行传播
	private static final ThreadLocal<TransactionInfo> transactionInfoHolder =
			new NamedThreadLocal<TransactionInfo>("Current aspect-driven transaction");

	// bean的两个属性,bean初始化的时候必须设置,否则会报错,后面会检查
	private PlatformTransactionManager transactionManager;
	private TransactionAttributeSource transactionAttributeSource;

	// spring 事务处理的主流程
	protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
			throws Throwable 

        // 解析事务属性
		final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
		// 获取事务管理器,根据配置文件中配置的事务管理beanId, 从spring容器中生成事务管理器bean(bean也在配置文件中配置了) 
		final PlatformTransactionManager tm = determineTransactionManager(txAttr);
		// 增强方法标识, com.lzg.note.aop.TestA.insert(包名+类名+方法名)
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
		// true 走这里 
		if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) 
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
            // 生成事务如果需要的,根据事务的传播行为
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
			Object retVal;
			try 
                // 回调处理,继续走其他的切面增强,和目标方法
				retVal = invocation.proceedWithInvocation();
			
			catch (Throwable ex) 
				// target invocation exception
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			
			finally 
			    // 清除事务相关的数据, 主要是thradLocal中的,同时会恢复之前被挂起的事务(如果之前有挂起的事务的话)
				cleanupTransactionInfo(txInfo);
			
			// 目标方法处理完成,处理完成,事务提交,或者回滚, 最后会进行 resume, 如果之前进行过suspend操作的话
			commitTransactionAfterReturning(txInfo);
			return retVal;
		 else // 非核心代码删除 
	

	/**
	 * 获取事务管理器,根据配置
	 */
	protected PlatformTransactionManager determineTransactionManager(TransactionAttribute txAttr)
        // Do not attempt to lookup tx manager if no tx attributes are set
        if (txAttr == null || this.beanFactory == null) 
          return getTransactionManager();
        

        String qualifier = txAttr.getQualifier();
        if (StringUtils.hasText(qualifier)) 
          return determineQualifiedTransactionManager(qualifier);
        
        // 解析配置文件的时候已经设置了 
        else if (StringUtils.hasText(this.transactionManagerBeanName)) 
          return determineQualifiedTransactionManager(this.transactionManagerBeanName);
         else  //删除非核心代码 
        
        private PlatformTransactionManager determineQualifiedTransactionManager (String qualifier)
          PlatformTransactionManager txManager = this.transactionManagerCache.get(qualifier);
          if (txManager == null) 
            // 从容器中获取
            txManager = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
                    this.beanFactory, PlatformTransactionManager.class, qualifier);
            this.transactionManagerCache.putIfAbsent(qualifier, txManager);
          
          return txManager;
        

        // 根据传播机制,进行生成/取出/挂起已有的事务	
        protected TransactionInfo createTransactionIfNecessary (
                PlatformTransactionManager tm, TransactionAttribute txAttr,
        final String joinpointIdentification)

          TransactionStatus status = null;
          if (txAttr != null) 
            if (tm != null) 
              // 根据传播机制,进行生成/取出/挂起已有的事务
              status = tm.getTransaction(txAttr);
            
          
          // 包装事务状态到事务信息中, txInfo
          return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
        

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

          TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
          // The transaction manager will flag an error if an incompatible tx already exists.
          txInfo.newTransactionStatus(status);
          // 设置到threadLocal, 同时如果已经有txInfo存在,则把上一个保存到oldTxInfo字段中,后续resumer的时候会用到
          txInfo.bindToThread();
          return txInfo;
        

        /**
         * Execute after successful completion of call, but not after an exception was handled.
         * Do nothing if we didn't create a transaction.
         * @param txInfo information about the current transaction
         */
        protected void commitTransactionAfterReturning (TransactionInfo txInfo)
          if (txInfo != null && txInfo.hasTransaction()) 
            txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
          
        

        /**
         * Handle a throwable, completing the transaction.
         * We may commit or roll back, depending on the configuration.
         * @param txInfo information about the current transaction
         * @param ex throwable encountered
         */
        protected void completeTransactionAfterThrowing (TransactionInfo txInfo, Throwable ex)
          if (txInfo != null && txInfo.hasTransaction()) 
            if (logger.isTraceEnabled()) 
              logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
                      "] after exception: " + ex);
            
            if (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 ex2) 
                logger.error("Application exception overridden by rollback exception", ex);
                throw ex2;
               catch (Error err) 
                logger.error("Application exception overridden by rollback error", ex);
                throw err;
              
             else spring4.0事务超详细源码解析

(转)MySQL优化笔记--锁机制超详细解析(锁分类事务并发引擎并发控制)

YOLOv5源码逐行超详细注释与解读——项目目录结构解析

HashMap底层源码解析下(超详细图解)

超详细的java线程池源码解析

mybatis源码-解析配置文件之配置文件Configuration解析(超详细, 值得收藏)