Spring源码分析之事务

原创
2019/06/10 14:13
阅读数 74

前言

本篇以@EnableTransactionManagement注解的方式来讲解Spring事务的实现

@EnableTransactionManagement配置

proxyTargetClass配置

在Spring中其事务是利用动态代理实现,动态代理有2种实现方式:

  • false:基于CGLIB来实现

  • true:基于Java原生的Proxy实现,这种方式原类必须要定义接口。

这个参数就是表示动态代理实现方式,如果值设置true,表示需要代理类都基于CGLIB来实现;默认情况下值是设置成false表示如果原类如果定义了接口则通过Proxy实现否则基于CGLIB来实现。

adviceMode配置

配置动态代理的织入方式

  • PROXY:JDK动态代理

  • ASPECTJ:AspectJ实现的代理

proxyTargetClass是配置PROXY的情况下才能生效

@Transactional配置

value事务管理类配置

根据value值获取Spring获取事务管理类PlatformTransactionManager,来进行事务管理。

propagation事务传播方式配置

Propagation.MANDATORY(强制性的事务)

当前必须存在一个事务,否则抛出异常,主要功能就是保证能加入到主事务,主事务不存在就会抛异常。

Propagation.REQUIRED(必填的事务)

如果当前已经存在事务,那么加入该事务,如果不存在事务,创建一个事务,这是默认的传播属性值。

Propagation.NEVER(从不)

当前事务不能合并到主事务,如果已经存在主事务则报错,这个跟MANDATORY相反。

Propagation.NOT_SUPPORTED(不支持事务)

以非事务方式执行操作,如果当前存在事务,就把当前事务挂起,挂起的原理就是将ThreadLocal缓存删掉,回到主事务后重新设置。

Propagation.REQUIRES_NEW(创建新事务)

处理从事务如果当前有主事务,将主事务挂起,创建新的事务作为当前事务,从事务处理完毕后,将主事务还原

Propagation.NESTED(嵌套事务)

利用savepoint创建主事务保存点,如果从事务异常,则可以从保存点开始继续执行主事务。

isolation事务隔离级别配置

DEFAULT:默认隔离级别

使用数据库设置的隔离级别

READ_UNCOMMITTED:读未提交隔离级别

使用读可提交隔离级别

READ_COMMITTED:读已提交隔离级别

使用读已提交隔离级别

REPEATABLE_READ:可重复读隔离级别

使用可重复读隔离级别

SERIALIZABLE:串行化隔离级别

使用串行化隔离级别

具体事务隔离级别细节可参考:https://my.oschina.net/u/945573/blog/2242185

timeout事务超时时间配置

事务超时时间设置timeout,其底层是通过Statement#setQueryTimeout()设置,一个事务可能有多个Statement,所以Spring通过累计每个Statement时间去计算事务超时时间,目前Spring事务集成MyBatis上设置这个参数是不生效。

readOnly事务是否只能查询不能修改配置

设置事务仅支持查询操作不支持修改操作。

rollbackFor && rollbackForClassName 需要回滚的异常类配置

根据抛出异常的对象的类或者类的名称来匹配,匹配上则回滚,例如设置 rollbackFor=IOError.class ,如果抛出的异常类是IOError或其子类则回滚

noRollbackFor && noRollbackForClassName 不需要回滚的异常类配置

跟上面的配置相反,根据抛出异常的对象的类或者类的名称来匹配,匹配上则不回滚

原理

事务大致原理是通过AOP创建代理对象将开启事务和提交事务(或回滚事务)织入到事务执行的核心代码执行前和执行后,AOP实现的原来跟我之前写的文章类似:https://my.oschina.net/u/945573/blog/3047657

我们带着问题来了解下他的实现

如何创建事务的代理对象

在Spring启动时会解析@EnableTransactionManagement注解并通过解析@Import将事务的配置类导入,配置类有2个分别是AutoProxyRegistrar和ProxyTransactionManagementConfiguration。AutoProxyRegistrar会将代理对象的创建组件InfrastructureAdvisorAutoProxyCreator注册进Spring容器。

看InfrastructureAdvisorAutoProxyCreator继承关系就能发现其实现了BeanPostProcessor类,Spring容器每个类在创建的时候会调用BeanPostProcessor里的postProcessBeforeInitialization方法,在初始化结束的时候会调用postProcessAfterInitialization方法。BeanPostProcessor作用就是修改这个创建的对象,InfrastructureAdvisorAutoProxyCreator就是利用了BeanPostProcessor将原来的类替换成代理类。

在创建代理过程中如何知道该类是否需要被替换成事务代理对象

上篇文章讲过AOP的组成有Advisor(切面),Pointcut(切点),Advice(增强),Advisor包含Pointcut和Advice。Pointcut表示切入的位置,在Spring中Pointcut接口是做一个匹配的功能包括Class和Method的匹配,只有匹配上才能做进一步增强。所以Spring查找容器中所有Advisor对象,然后取出Pointcut去匹配该类上是否注解了@Transactional,如果是则该类需要做代理。如果该类上没有注解则继续查找该类方法上是否注解了@Transactional,如果是则该类需要做代理。

Advisor是什么时候注册到Spring容器的

之前讲过导入的配置类有2个分别是AutoProxyRegistrar和ProxyTransactionManagementConfiguration,Advisor正是通过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;
	}

	@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) {
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}

}

这个类不仅注册了Advisor对象,还有TransactionAttributeSource和TransactionInterceptor。

  • TransactionAttributeSource类是@Transactional解析器,能根据Method或者Class对象将Method或者Class上的@Transactional配置的属性解析出来。

  • TransactionInterceptor就是Advice增强器,增强器作用就是会拦截事务方法的调用,在事务方法调用前开启事务调用后提交或者回滚事务。

如何对事务进行管理

不管是JPA还是JDBC,Spring都是通过PlatformTransactionManager类来管理事务,Spring通过@Transactional的value配置的bean名称查找Spring容器中的PlatformTransactionManager对象,默认情况下value值为空,会获取Spring容器中的PlatformTransactionManager类型的对象作为事务管理器。看下PlatformTransactionManager接口

public interface PlatformTransactionManager {

	TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

	void commit(TransactionStatus status) throws TransactionException;

	void rollback(TransactionStatus status) throws TransactionException;

}

getTransaction方法作用是开启事务,TransactionDefinition类型的参数为事务的配置,返回值是TransactionStatus类型事务的状态。commit和rollback分别对应事务的提交和回滚。

展开阅读全文
打赏
0
0 收藏
分享
加载中
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部