Spring事务原理探究

一、spring事务使用流程

1、使用spring提供的事务管理的时候,需要向容器中注入数据源 DataSource、注入事务管理器 PlatformTransactionManager,然后开启事务管理 @EnableTransactionManagement

2、上面三步执行完毕之后,就可以在需要使用事务管理的类或者方法上使用 @Transactional注解即可。

二、Spring事务原理探究

Ⅰ、spring事务执行流程

1、首先,在容器启动的时候,会向容器中注册数据源、事务管理器、事务属性、事务拦截器等

2、Spring容器启动过程中,会为标注了 @Transactional注解的类或方法创建一个代理对象

3、当执行具有事务管理的事务方法的时候,会执行代理对象中的代理方法(代理对象中保存了方法的增强器、目标对象、事务属性等信息)。

4、在执行目标方法前首先会执行事务拦截器链,然后执行事务拦截器链上的一个个拦截器(默认只有一个事务拦截器)

5、执行事务拦截器的时候,先从容器中获取该方法上的相关事务属性信息,然后获取事务管理器 PlatformTransactionManager

6、使用事务管理器开启一个事务

7、然后执行目标方法

​ ①、如果目标方法正常执行,则利用事务管理器提交事务

​ ②、如果目标方法执行出现异常,则利用事务管理器回滚事务

简而言之:容器会为标注了 @Transactional注解的事务方法或类创建一个代理对象,每当要执行事务方法的时候,会去执行代理对象中的方法(先执行事务拦截器获取事务管理器、事务属性等,使用事务管理器开启事务,然后执行目标方法、目标方法正常执行,则使用事务管理器提交事务。若目标方法异常执行,则使用事务管理器回滚事务)。

简单的说,spring的事务管理其实就是通过创建代理对象和拦截器,以及使用事务管理器帮我们自动的提交或回滚事务。不再需要我们手动的提交或回滚。

三、Spring事务源码解析

使用Spring的事务,最重要的一步就是:使用@EnableTransactionManagement注解开启事务管理,所以我们就以这个注解为突破口开始探究!

探究的过程分两大步进行:

1、该注解向容器中注入了什么组件(bean)?

2、该组件在什么时候起了什么作用 ?

(一)、EnableTransactionManagement

1、查看注解EnableTransactionManagement
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 可以看到在这里使用@Import和自定义Selector的方式在向容器中注册组件
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

	boolean proxyTargetClass() default false;

    // adviceMode默认就是PROXY,下面有用到
	AdviceMode mode() default AdviceMode.PROXY;

	int order() default Ordered.LOWEST_PRECEDENCE;
}

可以看到该注解使用了@Import注解和自定义Selector的方式向容器中导入组件,点击进入TransactionManagementConfigurationSelector中,查看该selector向容器中导入了什么组件

2、TransactionManagementConfigurationSelector

由上面的继承关系图可以看出 InfrastructureAdvisorAutoProxyCreator 类继承了 AbstractAutoProxyCreator类,重点探究该类

②、AbstractAutoProxyCreator类

可重点关注该类的几个方法:

这四个方法作用时机主要是在bean的实例化前后和初始化前后。

在这里插入图片描述

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

从上面代码可见,AutoProxyRegistrar类的主要作用就是向容器中注入了 InfrastructureAdvisorAutoProxyCreator组件,该组件是一个后置处理器,利用后置处理器机制在对象创建以后(初始化以后),包装对象,返回一个代理对象(代理对象中有包装事务拦截器、事务属性信息等)。



(三)、ProxyTransactionManagementConfiguration作用探究

由上面分析可知,EnableTransactionManagement注解向容器中注入了两个组件:AutoProxyRegistrar和ProxyTransactionManagementConfiguration,上面已经探究完了AutoProxyRegistrar的作用(bean创建的时候,给他创建代理对象),下面继续探究 ProxyTransactionManagementConfiguration 组件的作用时机以及作用。

1、ProxyTransactionManagementConfiguration源码
// 配置类
@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;
	}

    /**
    * 注册事务属性(即:@Transactional(rollbackFor = Exception.class)注解里可用的属性)
    * 上面的方法BeanFactoryTransactionAttributeSourceAdvisor会拿到这个事务属性并包装到增强器中
    */
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		return new AnnotationTransactionAttributeSource();
	}

    /**
    * 向容器中注入一个事务拦截器,他是一个方法拦截器,上面的方法
    * BeanFactoryTransactionAttributeSourceAdvisor会拿到这个拦截器并包装到增强器中
    */
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionInterceptor transactionInterceptor() {
		TransactionInterceptor interceptor = new TransactionInterceptor();
        // 拦截器里面保存了事务属性信息
		interceptor.setTransactionAttributeSource(transactionAttributeSource());
		if (this.txManager != null) {
            // 拦截器里面保存了事务管理器
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}
}

从上面的源码中可以看到,该类向容器中注入了三个组件:

**1、增强器:**BeanFactoryTransactionAttributeSourceAdvisor,容器启动的时候,增强器会被包装成拦截器链,当执行代理对象的方法的时候,就会先按照一定顺序执行拦截器链,即:这里是执行TransactionInterceptor里的invoke()方法。所以重点关注TransactionInterceptor。

**2、事务拦截器:**TransactionInterceptor ,用于拦截事务方法执行

**3、事务属性:**AnnotationTransactionAttributeSource,用于解析事务注解
这三个组件最后都会被包装到代理对象中!!!

2、关注事务拦截器(拦截到事务方法)
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

public Object invoke(final MethodInvocation invocation) throws Throwable {
		
    	// 获取目标类
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

		// 点进去,事务方法执行的地方,见下面的 《3》
		return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
			@Override
			public Object proceedWithInvocation() throws Throwable {
				return invocation.proceed();
			}
		});
	}
}
3、事务方法的执行过程
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {

    // 重点方法
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, txAttr);

		if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
            // 使用getTransaction和提交/回滚调用的标准事务界定
            // 创建事务
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
			Object retVal = null;
			try {
                // 这里执行事务方法,如果出现异常,则执行catch里面的方法通过事务管理器回滚。
                // 可以跟进去深入研究,先调用拦截器,再调用目标方法(责任链模式调用)
				retVal = invocation.proceedWithInvocation();
			}catch (Throwable ex) {
                // 如果事务方法执行异常,则在这里通过事务管理器回滚
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}finally {
				cleanupTransactionInfo(txInfo);
			}
            // 如果事务方法都成功执行完毕,则执行下面方法,通过事务管理器提交事务,点进去,见下面:
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}
    // 省略。。。

}

事务方法执行过程:

1、首先获取事务属性(若获取不到事务属性,则说明这是一个非事务方法)

2、然后获取事务管理器

3、通过事务管理器执行事务方法

4、回滚或提交

到这里,ProxyTransactionManagementConfiguration组件的作用也清楚了:往容器中注入事务方法拦截器,拦截每一个事务方法的执行。在事务方法执行前,先获取事务属性、事务管理器等,通过事务管理器来开启一个事务,然后执行目标方法,然后再通过事务管理器提交或回滚!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值