Spring源码学习之 五 事务

目录

事物概念解析

什么是事物?

事物的特性(ACID)

Spring事务三大接口介绍

PlatformTransactionManager接口介绍:

TransactionDefinition 定义事物属性

TransactionStatus接口介绍

SpringBoot  2.4.5 事务自动装配原理

spring-boot-autoconfigure.spring.factories中已导入事务自动装配类

@EnableTransactionManagement导入了TransactionManagementConfigurationSelector.class

我们先来看看AutoProxyRegistrar做了什么

ProxyTransactionManagementConfiguration的作用


事物概念解析

什么是事物?

事务是逻辑上的一组执行单元,要么都执行,要么都不执行

事物的特性(ACID)

ACID 是指数据库管理系统 DBMS 中事物所具有四个特性
eg: 在数据库系统中,一个事务由一系列的数据库操作组成一个完整的逻辑过程,比如银行转账,从
原账户扣除金额,目标账户增加金额
:atomicity 【原子性】
原子性表现为 操作不能被分割 ,那么这二个操作 要么 同时完成 ,要么就 全部不完成 ,若事务出错了,
那么事务就会回滚,
好像什么 都 没有发生过
:Consistency 【一致性】
一致性也比较容易理解,也就是说数据库要一直处于一致的状态,事务开始前是一个一致状态,
事务结束后是另一个一致状态,
事务将数据库从一个一致状态转移到另一个一致状态
:Isolation 【隔离性】
所谓的独立性就是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个
事务修改,只要另外一个事务还未提交,它所访问的数据就不受未提交事务的影响。换句话说,一个事
务的影响在该事务提交前对其它事务是不可见的
:Durability 【持久性】
若事务已经提交了,那么就回在数据库中永久的保存下来

Spring事务三大接口介绍

  • PlatformTransactionManager: (平台)事务管理器
  • TransactionDefinition: 事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则
  • TransactionStatus: 事务运行状态

PlatformTransactionManager接口介绍:

Spring 并不直接管理事务,而是提供了多种事务管理器 ,他们将事务管理的职责委托给 Hibernate 或者 JTA 等持
久化机制所提供的相关平台框架的事务来实现。通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现
就是各个平台自己的事情了。
public interface PlatformTransactionManager {
    /**
     * 获取事物状态
     */
    TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;

    /**
     * 事物提交
     */
    void commit(TransactionStatus status) throws TransactionException;

    /**
     * 事物回滚
     */
    void rollback(TransactionStatus status) throws TransactionException;
}

TransactionDefinition 定义事物属性

TransactionDefinition 接口中定义了 5个方法以及一些表示事务属性的常量比如隔离级别、传播行为等的常量。

TransactionStatus接口介绍

TransactionStatus 接口用来记录事务的状态 该接口定义了一组方法 ,用来获取或判断事务的相应状态信息。
PlatformTransactionManager.getTransaction(…) 方法返回一个 TransactionStatus 对象。返回的TransactionStatus
对象可能代表一个新的或已经存在的事务(如果在当前调用堆栈有一个符合条件的事物。
public interface TransactionStatus extends SavepointManager, Flushable {
    /**
     * 是否为新事物 *
     */
    boolean isNewTransaction();

    /**
     * 是否有保存点
     */
    boolean hasSavepoint();

    /**
     * 设置为只回滚
     */
    void setRollbackOnly();

    /**
     * 是否为只回滚
     */
    boolean isRollbackOnly();

    /**
     * 属性
     */
    @Override
    void flush();

    /**
     * 判断当前事物是否已经完成
     */
    boolean isCompleted();
}

SpringBoot  2.4.5 事务自动装配原理

spring-boot-autoconfigure.spring.factories中已导入事务自动装配类

org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
public class TransactionAutoConfiguration {

    ......

    @Configuration(proxyBeanMethods = false)
	@ConditionalOnBean(TransactionManager.class)
	@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
	public static class EnableTransactionManagementConfiguration {

		@Configuration(proxyBeanMethods = false)
		@EnableTransactionManagement(proxyTargetClass = false)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
				matchIfMissing = false)
		public static class JdkDynamicAutoProxyConfiguration {

		}

		@Configuration(proxyBeanMethods = false)
		@EnableTransactionManagement(proxyTargetClass = true)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
				matchIfMissing = true)
		public static class CglibAutoProxyConfiguration {

		}
	}
}

这里引入了@EnableTransactionManagement这个注解。熟悉spring的我们都知道,这个意味着开启事务管理。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {
    boolean proxyTargetClass() default false;

    AdviceMode mode() default AdviceMode.PROXY;

    int order() default 2147483647;
}

@EnableTransactionManagement导入了TransactionManagementConfigurationSelector.class

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
    protected String[] selectImports(AdviceMode adviceMode) {
        switch(adviceMode) {
        case PROXY:
        //默认PROXY
        //往容器中添加组件 : AutoProxyRegistrar和ProxyTransactionManagementConfiguration
            return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
        case ASPECTJ:
            return new String[]{this.determineTransactionAspectClass()};
        default:
            return null;
        }
    }
}

我们先来看看AutoProxyRegistrar做了什么

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		boolean candidateFound = false;
        //从我们传入进去的配置类上获取所有的注解的
		Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
        //循环注解
		for (String annType : annTypes) {
            //获取注解的元信息
			AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
			if (candidate == null) {
				continue;
			}
            //获取注解的mode属性
			Object mode = candidate.get("mode");
            //获取注解的proxyTargetClass
			Object proxyTargetClass = candidate.get("proxyTargetClass");
            //根据mode和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;
					}
				}
			}
		}
		
	}

}
	@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAutoProxyCreatorIfNecessary(registry, null);
	}
	@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {

		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	}
分析出 AutoProxyRegistrar 会为我们容器中导入了一个叫 InfrastructureAdvisorAutoProxyCreator 的组件
我们来看下 InfrastructureAdvisorAutoProxyCreator 继承图 , 有没有一点熟悉的味道
看看几个后置处理器做了什么事情
@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null;
			}
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

ProxyTransactionManagementConfiguration的作用

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    //导入了类型为BeanFactoryTransactionAttributeSourceAdvisor 的Bean:      org.springframework.transaction.config.internalTransactionAdvisor
	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {

		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
        //设置了事物源属性对象
		advisor.setTransactionAttributeSource(transactionAttributeSource);
        //设置了事物拦截器对象
		advisor.setAdvice(transactionInterceptor);
		if (this.enableTx != null) {
			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(TransactionAttributeSource transactionAttributeSource) {
		TransactionInterceptor interceptor = new TransactionInterceptor();
        //把事物属性源对象设置到我们的事物拦截器对象中
		interceptor.setTransactionAttributeSource(transactionAttributeSource);
        //把我们容器中的 事物对象配置到事物拦截器中
		if (this.txManager != null) {
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}

}

以上分析得知事物创建代理对象最主要的是InfrastructureAdvisorAutoProxyCreator的后置处理器为我们创建代理对象,实际上是他的父类AbstractAutoProxyCreator的postProcessAfterInitialization方法

	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                当前对象是否需要包装
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

创建事务代理对象流程图:


事务传播行为

spring事务的传播行为说的是,当多个事务同时存在的时候,spring如何处理这些事务的行为。

  • ① PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
  • ② PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
  • ③ PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
  • ④ PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
  • ⑤ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  • ⑥ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
  • ⑦ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。

Spring中的隔离级别

  • ① ISOLATION_DEFAULT:这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。
  • ② ISOLATION_READ_UNCOMMITTED:读未提交,允许另外一个事务可以看到这个事务未提交的数据。
  • ③ ISOLATION_READ_COMMITTED:读已提交,保证一个事务修改的数据提交后才能被另一事务读取,而且能看到该事务对已有记录的更新。
  • ④ ISOLATION_REPEATABLE_READ:可重复读,保证一个事务修改的数据提交后才能被另一事务读取,但是不能看到该事务对已有记录的更新。
  • ⑤ ISOLATION_SERIALIZABLE:一个事务在执行的过程中完全看不到其他事务对数据库所做的更新。

Spring事务失效的几种情况

  • 数据库引擎不支持事务,入使用Mysql的MyISAM存储引擎
  • 注解@Transactional所在类没有被Spring扫描,没有加@Service、@Component等注解
  • 注解@Transactional所在类不是public的
  • 外层方法没有加@Transactional注解:

       

  • @Transactional propagation 属性设置错误

       

       b方法新开了一个事务

  • 异常别吃了或者回滚异常类型不一致

     

      

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值