Spring事务源码阅读(注解式和xml配置式)

本文参考:《Spring源码深度解析》及源码走读.培养源码阅读思想

文章目录


先放图,du害一下大家, 在这里插入图片描述
在这里插入图片描述

1.必须懂的几个类

试想一下,如果Connection支持事务提交回滚(底层支持),那么你如何来设计你的事务处理框架?
我相信很多人的想法都是

  • 先读取 @Transation注解的属性.生成一个对象(存放事务相关)
  • 根据得到的该对象进行事务的commit,失败回滚,最终事务清除.

Spring框架对事务的支持大概也是这样的步骤,Spring支持嵌入事务,即方法中嵌套方法,如果都支持事务,则在里面的事务结束或者失败之后,外面的事务继续执行.
我们刚才提到 @Transation注解的属性提取,那么必定需要这样一个类去做提取的操作,提取的对象存储也需要一个相应类,用什么方式执行事务,这些都是我们后面需要讨论的内容,但是,在此之前,我们先看几个类,我们已经知道了实现事务的大概步骤,那么我们需要来看一下,Spring怎么去实现这些步骤的.

2.1 提取器驱动(装载)的advisor:BeanFactoryTransactionAttributeSourceAdvisor

我们知道Spring框架大量的使用了接口,可以想象,对于 @Transation注解的提取,Spring必定也是通过接口的实现类来定义提取方法(下一个会讲到),所以我们可以想象,我们需要一个类来承接这些接口和其他的属性.我们这里要讲的就是这个类。
我们看一下类上的注解:

  • Advisor driven by a TransactionAttributeSource, used to include a transaction advice bean for methods that are transactional.

包含一个 TransactionAttributeSource,用于事务通知。我们暂且不管 TransactionAttributeSource类的作用,目前我们可以知道的就是BeanFactoryTransactionAttributeSourceAdvisor他会装载和提供一个 TransactionAttributeSource类。
我们看他是怎么实现 TransactionAttributeSource的。

@SuppressWarnings("serial")
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
	
	//这个就是我们念念不忘的TransactionAttributeSource
	private TransactionAttributeSource transactionAttributeSource;

    //因为BeanFactoryTransactionAttributeSourceAdvisor 继承了PointCut接口,所以需要实现getPointCut方法
    //而获取到的PointCut类会返回我们需要的TransactionAttributeSource。
	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
		@Override
		protected TransactionAttributeSource getTransactionAttributeSource() {
			return transactionAttributeSource;
		}
	};
	
	@Override
	public Pointcut getPointcut() {
		return this.pointcut;
	}
}

很容易我们看到了TransactionAttributeSource 这个类,并且因为BeanFactoryTransactionAttributeSourceAdvisor继承了Pointcut接口,需要实现getPointcut方法,相当于是
通过得到PointCut实现类,再获取TransactionAttributeSource

2.2 @Transation注解元数据提取器:TransactionAttributeSource

@Transation的提取需要一定的规则,而不同的方式可能对应不同的规则,所以Spring利用接口的方式,制定提取的抽象。通过继承实现不同的提取规则。
首先你要知道 TransactionAttributeSource是一个接口,我们看一下类的描述

  • Strategy interface used by TransactionInterceptor for metadata retrieval.
    Implementations know how to source transaction attributes, whether from configuration, metadata attributes at source level (such as Java 5 annotations), or anywhere else.

提供给TransactionInterceptor拦截器用于事务元数据提取的接口.
但是接口需要实现类,因为是注解解析,这边的具体实现类是 AnnotationTransactionAttributeSource
作为一个注解提取器, AnnotationTransactionAttributeSource如何实现提取呢?

3.1 真实注解处理器:TransactionAnnotationParser

这边就给你答案,那就是TransactionAnnotationParser,看到该类的构造方法.必定会注入SpringTransactionAnnotationParser,这个类,这也是我们后面处理注解需要注意的。

	public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
		this.publicMethodsOnly = publicMethodsOnly;
		this.annotationParsers = new LinkedHashSet<TransactionAnnotationParser>(2);
		this.annotationParsers.add(new SpringTransactionAnnotationParser());
		if (jta12Present) {
			this.annotationParsers.add(new JtaTransactionAnnotationParser());
		}
		if (ejb3Present) {
			this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
		}
	}

2.3 事务执行器\拦截器:TransactionInterceptor

首先知道一点就是 ****实现了 MethodInterceptor接口,需要实现这个类的 invoke方法,事务处理的具体逻辑就在这里,而 MethodInterceptor又会在代理创建的时候被调用,所以我们基本知道该拦截器实现事务管理是通过invoke方法在代理的时候实现。
我们在后面的描述中会讲到具体实现,别着急
关注一下类上的注释:

  • AOP Alliance MethodInterceptor for declarative transaction management using the common Spring transaction infrastructure (PlatformTransactionManager)
  • TransactionInterceptors are thread-safe.

事务管理线程安全

2. 事务管理入口

2.1 注解式

还记得开启事务的注解式什么吗?我错,我知道你不记得了。
开启事务的注解是 EnableTransactionManagement,我们可以查看一下这个注解的使用,

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
	boolean proxyTargetClass() default false;
	
	//实现事务的方式(proxy或者aspectj)
	AdviceMode mode() default AdviceMode.PROXY;
	
	int order() default Ordered.LOWEST_PRECEDENCE;
}

很好,我们看到这个注解有一个mode,能够配置事务管理实现的方式,默认是PROXY.
在注解上面有一个 @Import注解,如果你告诉我不懂,我就是一巴掌过去. @Import注解引入一个Selector类,我们要看一下他是做什么幺蛾子的。

3.1 事务管理选择器:TransactionManagementConfigurationSelector

这个注解继承了AdviceModeImportSelector,实现selectImport方法,朔本回源,在Mvc启动的时候会调用Selector,也就是这样启动的.这边我们不细究,知道一个大概:

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
				return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
			default:
				return null;
		}
	}
}

这里看到了AdviceMode 的选择,我们只分析PROXY的方式,不要问为什么,问就是我菜.
PROXY的方式会返回两个类:AutoProxyRegistrar
ProxyTransactionManagementConfiguration

幺蛾子就出在这里面.

4.1 注册代理构造器:AutoProxyRegistrar

这个类只有一个方法,这个方法会去注册一些BeanDefinition.

@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		boolean candidateFound = false;
		Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
		for (String annoType : annoTypes) {
			AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
			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) {
					//重要的地方我只看到这里
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					if ((Boolean) proxyTargetClass) {
						AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
						return;
					}
				}
			}
		}
	}

虽然这个类叽里呱啦的说了一堆,但是重要的是这一行代码,这个方法会为我们注册一个很重要的类:InfrastructureAdvisorAutoProxyCreator,自动代理构造器,我们对于advisor的查找和代理的实现都在这个类中实现,后面我们会说道。

	AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);

	public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAutoProxyCreatorIfNecessary(registry, null);
	}

	public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	}

4.2 事务注解驱动配置:ProxyTransactionManagementConfiguration

这个类,会为我们注册几个Bean,就是我们一开头说的,事务注解元数据提取器事务处理拦截器提取器承载类

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

	//事务注解提取器的承载类
	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		//注入事务注解提取器
		advisor.setTransactionAttributeSource(transactionAttributeSource());
		//注入拦截器
		advisor.setAdvice(transactionInterceptor());
		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() {
		TransactionInterceptor interceptor = new TransactionInterceptor();
		//注入事务注解提取器
		interceptor.setTransactionAttributeSource(transactionAttributeSource());
		if (this.txManager != null) {
			//事务管理器:PlatformTransactionManager
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}

}

2.2 XML式

3.1 事务命名空间处理器:TxNamespaceHandler

这个类实现了NameSpaceHandler,Spring框架会实现NamespaceHandler接口实现类的调用,这个我们暂时不管他。
可以想象到,和注解处理的方式应该类似,这边也应该注入,我们刚才讲的三个类.所以我们来看一下代码实现

	@Override
	public void init() {
		registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
	}

这边注册了三个BeanDefinitionParser的类,用屁股想象都知道,他大概想要去做什么事情,但是我们还是一个一个来看一下.

4.1 TxAdviceBeanDefinitionParser:注册事务注解提取器(或直接读取事务配置)

看到这边会去提取xml的元素,然后判断是否手动在XML中写入了事务相关属性,parseAttributeSource这个方法会去解析相关的属性(只读、超时时间…)
如果不是xml方式去注入的话,就需要去注册一个AnnotationTransactionAttributeSource,让这个类去提取**@Transational**上的属性,然后生成对应类.

	@Override
	protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
		builder.addPropertyReference("transactionManager", TxNamespaceHandler.getTransactionManagerName(element));

		List<Element> txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES_ELEMENT);
		if (txAttributes.size() > 1) {
			parserContext.getReaderContext().error(
					"Element <attributes> is allowed at most once inside element <advice>", element);
		}
		else if (txAttributes.size() == 1) {
			// Using attributes source.
			Element attributeSourceElement = txAttributes.get(0);
			RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext);
			builder.addPropertyValue("transactionAttributeSource", attributeSourceDefinition);
		}
		else {
			// Assume annotations source.
			builder.addPropertyValue("transactionAttributeSource",
					new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"));
		}
	}

4.2 注册事务基础Bean配置

等下我们看代码的时候你会发现,他实现了和事务注解驱动配置:ProxyTransactionManagementConfiguration类似的功能:

	@Override
	public BeanDefinition parse(Element element, ParserContext parserContext) {
		registerTransactionalEventListenerFactory(parserContext);
		String mode = element.getAttribute("mode");
		if ("aspectj".equals(mode)) {
			// mode="aspectj"
			registerTransactionAspect(element, parserContext);
		}
		else {
			// mode="proxy"
			AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
		}
		return null;
	}

这边我们依然只看PROXY的方式,我们可以看到下面的代码基本可以分成四步:

  • AopNamespaceUtils.registerAutoProxyCreatorIfNecessary:注册InfrastructureAdvisorAutoProxyCreator以及xml配置的解析,不具体看了
  • 注入AnnotationTransactionAttributeSource
  • 注入TransactionInterceptor
  • 注入BeanFactoryTransactionAttributeSourceAdvisor
  • 注册上述的组件到context
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
			//注册InfrastructureAdvisorAutoProxyCreator类和解析XML属性
			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);

				//注入BeanFactoryTransactionAttributeSourceAdvisor
				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);
				
				//注册到context
				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);
			}
		}
	}

4.3 注册事务管理器

这个类应该是解析xml上面的注解来注册事务管理器的,我们看一下这边的注释

  • Parser for the tx:jta-transaction-manager/ XML configuration element, autodetecting WebLogic and WebSphere servers and exposing the corresponding JtaTransactionManager subclass.

代码里面会根据不同的方式去注册事务管理器.

	static String resolveJtaTransactionManagerClassName() {
		if (weblogicPresent) {
			return WEBLOGIC_JTA_TRANSACTION_MANAGER_CLASS_NAME;
		}
		else if (webspherePresent) {
			return WEBSPHERE_TRANSACTION_MANAGER_CLASS_NAME;
		}
		else {
			return JTA_TRANSACTION_MANAGER_CLASS_NAME;
		}
	}

3. 构造器:事务拦截器基本配置查找与生成代理

废话不多说,我们来看一下InfrastructureAdvisorAutoProxyCreator这个类,这个类隔代实现了BeanPostProcessor接口,对于BeanPostProcessor,我们看一下类的注释

  • Factory hook that allows for custom modification of new bean instances, e.g. checking for marker interfaces or wrapping them with proxies.

大概就是为Bean工厂创建的Bean实例提供一个钩子,在Bean调用之前做一些修饰操作.
实现postProcessAfterInitialization才能实现上面所说的操作,我们看一下这个方法:
注意类上的注释:通过配置监听器实现代理,这边设置缓存用过特定key查找,没有找到会进入wrapIfNecessary方法,根据注释,我们可以知道,这个方法大概就是要去生成一个代理了。

	/**
	 * Create a proxy with the configured interceptors if the bean is
	 * identified as one to proxy by the subclass.
	 * @see #getAdvicesAndAdvisorsForBean
	 */
	@Override
	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;
	}

通过一些列的查找,如果找到对应的代理类就直接返回,否则

  • 先去查找拦截器
  • 在通过拦截器实现代理
	/**
	 * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
	 * @param bean the raw bean instance
	 * @param beanName the name of the bean
	 * @param cacheKey the cache key for metadata access
	 * @return a proxy wrapping the bean, or the raw bean instance as-is
	 */
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// 查找拦截器
		Object[] 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;
	}

我们下面通过这两部分来分析一下

2.1 拦截器查找

这里进入拦截器的查找,如果查找到的拦截器为空, 返回空数组,否则返回拦截器数组

	@Override
	protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
		List<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();
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

3.1 查找所有拦截器

这边的这个方法处理是这样的

  • 从BeanFactory(或者缓存数组)中拿到advisor的字符串名称
  • 进行一些判断,然后从BeanFactory里面获取Advisor实例
  • 组装List返回

虽然我不知道BeanFactory怎么去拿到这些advisor,能力有限,以后再看,但是我们刚才开篇注册的三个Advisor这边应该是可以拿到的。

	public List<Advisor> findAdvisorBeans() {
		String[] advisorNames = null;
		synchronized (this) {
			advisorNames = this.cachedAdvisorBeanNames;
			//从BeanFactory(或者缓存数组)中拿到advisor的字符串名称
			if (advisorNames == null) {
				advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Advisor.class, true, false);
				this.cachedAdvisorBeanNames = advisorNames;
			}
		}
		if (advisorNames.length == 0) {
			return new LinkedList<Advisor>();
		}

		List<Advisor> advisors = new LinkedList<Advisor>();
		for (String name : advisorNames) {
			if (isEligibleBean(name)) {
				if (this.beanFactory.isCurrentlyInCreation(name)) {
					//......................省略
					//进行一些判断,然后从BeanFactory里面获取Advisor实例
					advisors.add(this.beanFactory.getBean(name, Advisor.class));
					}
				}
			}
		}
		return advisors;
	}

3.2 根据找到的所有拦截器,查找合适的拦截器

这一步的操作关键的代码在这边,我们舍去一些操作,直接来看是怎么查找ApplyAdvisor的

	AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);

这边有一种Advisor叫做IntroductionAdvisor ,这个接口网上说好像是类级别上的增强,具体可以查阅对应资料,但是我们这边不关注这个类.
我们这边需要关注的是canApply这个方法,因为他是判断
Advisor
是否适用于当前事务管理的依据.

	public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		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) {
				// already processed
				continue;
			}
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}

往下看,这边可以看到,第二个if判断判断了类是否是PointcutAdvisor,刚才上面介绍的BeanFactoryTransactionAttributeSourceAdvisor类就是实现了PointcutAdvisor接口,所以这边他要起到作用了.
这边传入getPointcut方法返回的对象,在上面的介绍中说到,内部实现了TransactionAttributeSourcePointcut
即当前的getPointcut方法传入TransactionAttributeSourcePointcut

	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;
		}
	}

canApply方法需要关注两个地方

  • MethodMatcher的获取
  • 调用matches方法
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 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;
		}
		
		//循环通过MethodMatcher的matches方法匹配
		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;
	}

4.1 获取方法匹配器:MethodMatcher

上面说的,传入的pointcutTransactionAttributeSourcePointcut类,所以直接查看这个类是怎么获取MethodMatcher的:

	@Override
	public final MethodMatcher getMethodMatcher() {
		return this;
	}

这边看到实现的getMethodMatcher方法直接返回this,也就是说,返回的Match就是TransactionAttributeSourcePointcut

4.2 方法匹配器匹配,返回结果

既然我们已经知道了MethodMatcher,就要去看一下matchs到底是怎么匹配的.

	@Override
	public boolean matches(Method method, Class<?> targetClass) {
		if (TransactionalProxy.class.isAssignableFrom(targetClass)) {
			return false;
		}
		TransactionAttributeSource tas = getTransactionAttributeSource();
		return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
	}

从刚才的分析可以看到,这边拿到的TransactionAttributeSourcePointcutBeanFactoryTransactionAttributeSourceAdvisor类中的内部类,并实现了getTransactionAttributeSource方法.
可以参考上面介绍BeanFactoryTransactionAttributeSourceAdvisor,这里的TransactionAttributeSource注入的是AnnotationTransactionAttributeSource
所以我们来看一下这边的实现,依然是先通过缓存去获取,如果没有获取到才去解析。那么如何解析呢.

	@Override
	public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
		
		Object cacheKey = getCacheKey(method, targetClass);
		Object cached = this.attributeCache.get(cacheKey);
		if (cached != null) {
			if (cached == NULL_TRANSACTION_ATTRIBUTE) {
				return null;
			}
			else {
				return (TransactionAttribute) cached;
			}
		}
		else {
			TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);
			// Put it in the cache.
			if (txAtt == null) {
				this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
			}
			else {
				if (logger.isDebugEnabled()) {
					Class<?> classToLog = (targetClass != null ? targetClass : method.getDeclaringClass());
					logger.debug("Adding transactional method '" + classToLog.getSimpleName() + "." +
							method.getName() + "' with attribute: " + txAtt);
				}
				this.attributeCache.put(cacheKey, txAtt);
			}
			return txAtt;
		}
	}
5.1 解析@Transation注解

这边的解析分成四种情况,任意一种满足则退出,方法上的注释也说明了这些:

  • 解析当前方法上的注解
  • 解析当前类上的注解
  • 解析类实现的接口的方法上的注解
  • 解析类实现的接口上的注解
	protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
		// Don't allow no-public methods as required.
		if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
			return null;
		}

		// Ignore CGLIB subclasses - introspect the actual user class.
		Class<?> userClass = ClassUtils.getUserClass(targetClass);
		// The method may be on an interface, but we need attributes from the target class.
		// If the target class is null, the method will be unchanged.
		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.
		TransactionAttribute txAtt = findTransactionAttribute(specificMethod);
		if (txAtt != null) {
			return txAtt;
		}

		// Second try is the transaction attribute on the target class.
		txAtt = findTransactionAttribute(specificMethod.getDeclaringClass());
		if (txAtt != null && ClassUtils.isUserLevelMethod(method)) {
			return txAtt;
		}

		if (specificMethod != method) {
			// Fallback is to look at the original method.
			txAtt = findTransactionAttribute(method);
			if (txAtt != null) {
				return txAtt;
			}
			// Last fallback is the class of the original method.
			txAtt = findTransactionAttribute(method.getDeclaringClass());
			if (txAtt != null && ClassUtils.isUserLevelMethod(method)) {
				return txAtt;
			}
		}

		return null;
	}

解析的步骤不是重点,重点是如何去解析.
可以看到这边会拿到注解,然后循环查找合适的事务注解去解析并返回.
我们刚才看到在 AnnotationTransactionAttributeSource中会初始化SpringTransactionAnnotationParser对象

	protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {
		if (ae.getAnnotations().length > 0) {
			for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
				TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
				if (attr != null) {
					return attr;
				}
			}
		}
		return null;
	}

这边即通过SpringTransactionAnnotationParser来解析@Trasation注解,看一下代码即可,不重点分析

	@Override
	public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
		AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, 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"));
		ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<RollbackRuleAttribute>();
		Class<?>[] rbf = attributes.getClassArray("rollbackFor");
		for (Class<?> rbRule : rbf) {
			RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
			rollBackRules.add(rule);
		}
		String[] rbfc = attributes.getStringArray("rollbackForClassName");
		for (String rbRule : rbfc) {
			RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
			rollBackRules.add(rule);
		}
		Class<?>[] nrbf = attributes.getClassArray("noRollbackFor");
		for (Class<?> rbRule : nrbf) {
			NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
			rollBackRules.add(rule);
		}
		String[] nrbfc = attributes.getStringArray("noRollbackForClassName");
		for (String rbRule : nrbfc) {
			NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
			rollBackRules.add(rule);
		}
		rbta.getRollbackRules().addAll(rollBackRules);
		return rbta;
	}


2.2 生成代理

上面的步骤结束,已经拿到所有类和方法对应的拦截器数组.即生成代理.
这边不赘述,参考另一篇博文:Spring代理创建和代理实现

4. 事务拦截器

2.1 需要懂的事务相关的几个类

3.1 事务信息承载器:TransactionInfo

看一下注释的内容:

  • Opaque object used to hold Transaction information. Subclasses must pass it back to methods on this class, but not see its internals.

这个类其实是用来承载解析出来的事务属性集、事务状态的类。记录事务的信息主要是在事务执行的生命周期中,Spring可以把控当前事务。他的内部包含了下面几个类。

	protected final class TransactionInfo {

		private final PlatformTransactionManager transactionManager;

		private final TransactionAttribute transactionAttribute;

		private final String joinpointIdentification;

		private TransactionStatus transactionStatus;

		private TransactionInfo oldTransactionInfo;
}

3.2 事务属性:TransactionAttribute

刚才上面的解析器Parse代码里面已经说明,这个类是用来承载**@Transaction**注解带来的属性的.

3.3 事务状态:TransactionStatus

这个接口是操作事务最关键的类,它能够实现保存点操作判断事务状态等.具体实现在后面的描述中给出
看一下接口上的注释:

  • programmatically request a rollback (instead of throwing an exception that causes an implicit rollback).
  • Derives from the SavepointManager interface to provide access to savepoint management facilities. Note that savepoint management is only available if supported by the underlying transaction manager.

2.2 事务拦截器实现

事务拦截器实现了MethodInterceptor,上面生成代理的时候会把TransactionInterceptor添加到对应calss的method中.
现在分析一下他的实现:
关注invoke方法:

	@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);

		// Adapt to TransactionAspectSupport's invokeWithinTransaction...
		return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
			@Override
			public Object proceedWithInvocation() throws Throwable {
				return invocation.proceed();
			}
		});
	}

重写了proceedWithInvocation()方法,调用传入的MethodInvocation的proceed方法.
可以这样理解,传进来的MethodInvoke代表某个正在执行的业务方法或者事务(嵌套事务),那么事务执行的操作应该是这样的

{
	事务开始
	try{
		执行业务方法、或者嵌入事务.
	}catch{
		回滚操作
	}finally{
		事务提交、状态清除等.
	}
}

我们具体看一下代码:

protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
			throws Throwable {

		// If the transaction attribute is null, the method is non-transactional.
		final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
		final PlatformTransactionManager tm = determineTransactionManager(txAttr);
		//事务的标识
		final String joinpointIdentification = methodIdentification(method, targetClass);

		//声明式事务
		if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
			//开启事务
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
			Object retVal = null;
			try {
				//执行具体方法
				// This is an around advice: Invoke the next interceptor in the chain.
				// This will normally result in a target object being invoked.
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				//事务回滚
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				//清理操作
				cleanupTransactionInfo(txInfo);
			}
			//事务提交
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}

		else {
			//编程式事务不管
			try {
				Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
						new TransactionCallback<Object>() {
						}
			}
		}
	}

我们从上面代码可以看到基本是这样的情况,这边只分析声明式事务的处理.

3.1 构造事务信息承载器:TransactionInfo

事务信息承载,最重要的是TransationStatus,所以这边的代码分两个步骤:

  • 获取TransationStatus
  • 构造TransactionInfo
	protected TransactionInfo createTransactionIfNecessary(
			PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {

		// If no name specified, apply method identification as transaction name.
		if (txAttr != null && txAttr.getName() == null) {
			txAttr = new DelegatingTransactionAttribute(txAttr) {
				@Override
				public String getName() {
					return joinpointIdentification;
				}
			};
		}
		
		//获取事务状态
		TransactionStatus status = null;
		if (txAttr != null) {
			if (tm != null) {
				status = tm.getTransaction(txAttr);
			}
			else {
				//日志
			}
		}
		//构造TransactionInfo
		return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
	}

3.2 获取TransationStatus

这边通过传入的TransationAttribute实现事务的管理。分为三个重要的步骤:拿到事务对象、判断当前存在事务和不存在事务

@Override
	public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
		//拿到事务对象
		Object transaction = doGetTransaction();
		//存在事务
		if (isExistingTransaction(transaction)) {
			// Existing transaction found -> check propagation behavior to find out how to behave.
			return handleExistingTransaction(definition, transaction, debugEnabled);
		}

		//是否超时
		if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
		}
		
		//不存在事务
		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);
			if (debugEnabled) {
				logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
			}
			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);
		}
	}

4.1 拿到事务对象

设置保存点,获取相应资源

	@Override
	protected Object doGetTransaction() {
		DataSourceTransactionObject txObject = new DataSourceTransactionObject();
		txObject.setSavepointAllowed(isNestedTransactionAllowed());
		ConnectionHolder conHolder =
				(ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
		txObject.setConnectionHolder(conHolder, false);
		return txObject;
	}

4.2 存在事务

存在事务的情况,这边会根据Spring定义的事务的传播状态去处理,分别为:

  • 不支持事务:报错
  • 执行非事务处理,如果存在的话,暂停当前事务(挂起)
  • 如果新事务的传播机制是RequireNew,把正在执行的事务挂起.
  • 嵌入式事务
    • 支持设置保存点,创建保存点
    • 不支持设置保存点,挂起当前事务执行新事务

保存点可以通过Connection来处理,这边不关心底层的实现

	private TransactionStatus handleExistingTransaction(
			TransactionDefinition definition, Object transaction, boolean debugEnabled)
			throws TransactionException {
		//不支持事务:报错
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
			throw new IllegalTransactionStateException(
					"Existing transaction found for transaction marked with propagation 'never'");
		}
		//执行非事务处理,如果存在的话,暂停当前事务(挂起)
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
			Object suspendedResources = suspend(transaction);
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(
					definition, null, false, newSynchronization, debugEnabled, suspendedResources);
		}
		//如果新事务的传播机制是RequireNew,把正在执行的事务挂起.
		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;
			}
		}
		//嵌入式事务  支持设置保存点,创建保存点 
		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()) {
				DefaultTransactionStatus 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;
			}
		}
		//..............略
	}
5.1 设置Spring管理Connection及属性

doBegin方法获取连接,交由Spring管理,主要关注DataSourceTransactionManager这个类的具体实现包括下面几个部分:

  • 尝试获取连接,获取不到则创建连接
  • 设置事务隔离级别
  • 更改自动提交设置,将提交给Spring实现
  • 激活事务、设置超时时间
  • 将连接绑定到当前线程
  • 如果异常,释放连接
    @Override
    protected void doBegin(Object transaction, TransactionDefinition definition) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
        Connection con = null;

        try {
            //尝试获取连接,获取不到则创建连接
            if (txObject.getConnectionHolder() == null || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
                Connection newCon = this.dataSource.getConnection();
              	txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
            }
            txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
            con = txObject.getConnectionHolder().getConnection();
			//设置事务隔离级别
            Integer previousIsolationLevel = org.springframework.jdbc.datasource.DataSourceUtils.prepareConnectionForTransaction(con, definition);
            txObject.setPreviousIsolationLevel(previousIsolationLevel);
			//更改自动提交设置,将提交给Spring实现
            if (con.getAutoCommit()) {
                txObject.setMustRestoreAutoCommit(true);
                con.setAutoCommit(false);
            }
            //激活事务、设置超时时间
            txObject.getConnectionHolder().setTransactionActive(true);
            int timeout = determineTimeout(definition);
            if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
                txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
            }

            if (txObject.isNewConnectionHolder()) {
                //将连接绑定到当前线程
                TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
            }
        }
        catch (Throwable ex) {
            if (txObject.isNewConnectionHolder()) {
               	//异常释放连接
                org.springframework.jdbc.datasource.DataSourceUtils.releaseConnection(con, this.dataSource);
                txObject.setConnectionHolder(null, false);
            }
            throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
        }
    }
5.2 将事务信息记录到事务队列管理器
    protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
        /**
         * 如果是新的事务,要把事务信息记录到事务管理器中
         */
        if (status.isNewSynchronization()) {
            TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
            TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
                definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
                    definition.getIsolationLevel() : null);
            TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
            TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
            TransactionSynchronizationManager.initSynchronization();
        }
    }

4.3 不存在事务

5.1 设置Spring管理Connection及属性

同上

5.2 将事务信息记录到事务队列管理器

同上

3.3 构造TransactionInfo

这边比较关键的一步就是绑定事务到线程.从注释上面看,是为了正确管理,即使没有创建事务的情况。
而bindToThread其实是维护了一个ThreadLocal的变量。

	 */
	protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm,
			TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) {
		
		//构造TransactionInfo 
		TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
		if (txAttr != null) {
			txInfo.newTransactionStatus(status);
		}
		else {
			//日志
		}

		// 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.
		//绑定到线程
		txInfo.bindToThread();
		return txInfo;
	}

2.3 执行相应业务方法

这一步就是方法的调用,没有特别指的分析的地方:

	return invocation.proceedWithInvocation();
	return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
			@Override
			public Object proceedWithInvocation() throws Throwable {
				return invocation.proceed();
			}
	});

2.4 事务异常处理

事务异常分成两种情况,如果抛出RunTimeExceptionError直接回滚,其他异常会尝试提交

protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
        /**
         * 57.当抛出异常时首先判断当前是否存在事务,这是基本依据
         */
        if (txInfo != null && txInfo.hasTransaction()) {
           	//对于RunTimeException或Error的异常会终止提交
            if (txInfo.transactionAttribute.rollbackOn(ex)) {
                try {
                    //回滚操作
                    txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
                }
                catch (TransactionSystemException ex2) {.//.....略
                }
            }
           	//其他的异常依然会操作提交
            else {
                try {
                    txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
                }
                catch (TransactionSystemException ex2) {
                  //........略}
            }
        }
    }

3.1 事务回滚

事务回滚会先判断状态,如果已经提交(有这种情况?),直接报错,不然利用Connection的Api处理回滚

    @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;
        //处理回滚
        processRollback(defStatus);
    }

回滚分成几种情况

  • 通过保存点进行回滚
  • 新事务通过Connection的api调用回复
  • 其他则设值回滚标识
  • 事务处理结束之后的信息清除
    private void processRollback(DefaultTransactionStatus status) {
        try {
            try {
                /**
                 * 自定义触发器的调用,注册参考
                 * @see TransactionSynchronizationManager#registerSynchronization(TransactionSynchronization)
                 */
                triggerBeforeCompletion(status);
               //通过保存点信息进行回滚
                if (status.hasSavepoint()) {
                    status.rollbackToHeldSavepoint();
                }
                //如果是新的事务,直接回滚,这边也是通过Connection回滚
                else if (status.isNewTransaction()) {
                    doRollback(status);
                }
                else if (status.hasTransaction()) {
                    if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
                 		//标记为回滚状态,下一次执行的时候回滚
                        doSetRollbackOnly(status);
                    }
                    else {
                       //..............
                       }
            triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
        }
        finally {
            //事务处理结束之后的信息清除
            cleanupAfterCompletion(status);
        }
    }

通过保存点回滚也是直接调用Connection的api,如下:

  //从保存点回滚
  conHolder.getConnection().rollback((Savepoint) savepoint);
   //释放保存点
  conHolder.getConnection().release((Savepoint) savepoint);

事务处理结束之后的信息清除和事务提交之后的finally操作一样,这边不赘述,往后看

2.5 TransactionInfo清除

重置TransactionInfo

    /**
     * Reset the TransactionInfo ThreadLocal.
     * <p>Call this in all cases: exception or normal return!
     */
    protected void cleanupTransactionInfo(TransactionInfo txInfo) {
        if (txInfo != null) {
            txInfo.restoreThreadLocalStatus();
        }
    }

2.6 事务提交

事务提交这边也分为几种情况:

  • 事务已经提交,报错
  • 标记为回滚,调用回滚方法(回滚方法中有一步处理就是设置这个标识)
  • 提交
public final void commit(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;
        //如果事务中已经被标记为回滚,则不尝试提交,直接回滚。
        if (defStatus.isLocalRollbackOnly()) {
            processRollback(defStatus);
            return;
        }
        if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
            processRollback(defStatus);
            if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
                throw new UnexpectedRollbackException(
                    "Transaction rolled back because it has been marked as rollback-only");
            }
            return;
        }

      	//处理事务提交
        processCommit(defStatus);
    }

这边主要分成几步:

  • 存在保存点,说明有事务没有执行完不提交
  • 如果是新事务,说明事务执行完成了,调用Connectio.commit提交事务
  • 其他情况不提交,报错回滚或者抛错
  • finally清除操作
    private void processCommit(DefaultTransactionStatus status) throws TransactionException {
        try {
            boolean beforeCompletionInvoked = false;
            try {
                prepareForCommit(status);
                triggerBeforeCommit(status);
                triggerBeforeCompletion(status);
                beforeCompletionInvoked = true;
                boolean globalRollbackOnly = false;
                if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
                    globalRollbackOnly = status.isGlobalRollbackOnly();
                }
                if (status.hasSavepoint()) {
                  //存在保存点则清除,但不提交事务
                  status.releaseHeldSavepoint();
                }
                else if (status.isNewTransaction()) {
                    //独立新事务的提交---非独立新事物不提交
                    doCommit(status);
                }
               
            try {
                triggerAfterCommit(status);
            }
            finally {
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
            }

        }
        finally {
            /**
             * 83.提交后清除操作
             */
            cleanupAfterCompletion(status);
        }
    }

finally清除操作主要分成下面几步:

  • 修改事务状态
  • 新事务连接释放
  • 如果有事务被挂起,则唤醒对应事务
  private void cleanupAfterCompletion(DefaultTransactionStatus status) {
        //修改事务状态
        status.setCompleted();
        if (status.isNewSynchronization()) {
            //清除当前事务的同步信息
            TransactionSynchronizationManager.clear();
        }
        if (status.isNewTransaction()) {
            //事务连接释放
            doCleanupAfterCompletion(status.getTransaction());
        }
       	//如果当前事务执行前有事务被挂起,这边是设置一个Object的属性,这也是事务传播的一个处理
        if (status.getSuspendedResources() != null) {
            //恢复前一个挂起的事务
            resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources());
        }
    }
发布了82 篇原创文章 · 获赞 15 · 访问量 3112

猜你喜欢

转载自blog.csdn.net/qq_34326321/article/details/102986091
今日推荐