Spring 源码探索 之 声明式事务源码解读(一)

一、事务概念

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

ACID

ACID是指数据库管理系统DBMS中事物所具有四个特性。
在数据库系统中,一个事务由一系列的数据库操作组成一个完整的逻辑过程,比如银行转账,从原账户扣除金额,目标账户增加金额。

  • ①:atomicity【原子性】
    原子性表现为操作不能被分割,那么这二个操作 要么同时完成,要么就全部不完成,若事务出错了,那么事务就会回滚,
    好像什么 都 没有发生过
  • ②:Consistency【一致性】
    一致性也比较容易理解,也就是说数据库要一直处于一致的状态,事务开始前是一个一致状态,事务结束后是另一个一致状态,
    事务将数据库从一个一致状态转移到另一个一致状态
  • ③:Isolation【隔离性】
    所谓的独立性就是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修改,只要另外一个事务还未提交,它所访问的数据就不受未提交事务的影响。换句话说,一个事务的影响在该事务提交前对其它事务是不可见的
  • ④:Durability【持久性】
    若事务已经提交了,那么就回在数据库中永久的保存下来

二、Spring事务三大接口介绍

  • 2.1)PlatformTransactionManager: (平台)事务管理器

  • 2.2)TransactionDefinition: 事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则

  • 2.3)TransactionStatus: 事务运行状态

2.1)PlatformTransactionManager接口介绍

Spring并不直接管理事务,而是提供了多种事务管理器 ,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。
Spring事务管理器的接口是:
org.springframework.transaction.PlatformTransactionManager ,
通过这个接口,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;
}

2.2)TransactionDefinition 事物属性的定义
org.springframework.transaction.TransactionDefinition
TransactionDefinition接口中定义了5个方法以及一些表示事务属性的常量比如隔离级别、传播行为等等的常量。
我下面只是列出了TransactionDefinition接口中的方法而没有给出接口中定义的常量,该接口中的常量信息会在后面依次介绍到。

public interface TransactionDefinition {

	/**
	 * 支持当前事物,若当前没有事物就创建一个事物
	 * */
	int PROPAGATION_REQUIRED = 0;

    /**
     *  如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行
     * */
	int PROPAGATION_SUPPORTS = 1;

	/**
     *如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常
	 */
	int PROPAGATION_MANDATORY = 2;

    /**
     *创建一个新的事务,如果当前存在事务,则把当前事务挂起
     **/
	int PROPAGATION_REQUIRES_NEW = 3;

    /**
     *  以非事务方式运行,如果当前存在事务,则把当前事务挂起
     * */
	int PROPAGATION_NOT_SUPPORTED = 4;

    /**
     * 以非事务方式运行,如果当前存在事务,则抛出异常。
     * */
	int PROPAGATION_NEVER = 5;

    /**
     *  表示如果当前正有一个事务在运行中,则该方法应该运行在 一个嵌套的事务中,
        被嵌套的事务可以独立于封装事务进行提交或者回滚(保存点),
        如果封装事务不存在,行为就像 PROPAGATION_REQUIRES NEW
     * */
	int PROPAGATION_NESTED = 6;


	/**
     *使用后端数据库默认的隔离级别,Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别
	 */
	int ISOLATION_DEFAULT = -1;

	/**
     *最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
	 */
	int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;

	/**
     *允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
	 */
	int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;

	/**
     *对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生
	 */
	int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;

	/**
	 *最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,
	 * 也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能通常情况下也不会用到该级别
	 */
	int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;


	/**
     *使用默认的超时时间
	 */
	int TIMEOUT_DEFAULT = -1;


	/**
     *获取事物的传播行为
	 */
	int getPropagationBehavior();

	/**
     *获取事物的隔离级别
	 */
	int getIsolationLevel();

	/**
     *返回事物的超时时间
	 */
	int getTimeout();

	/**
     *返回当前是否为只读事物
	 */
	boolean isReadOnly();

	/**
     *获取事物的名称
	 */
	@Nullable
	String getName();

}

在这里插入图片描述

2.3)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();

}

三、@EnableTransactionManagement

我们来分析@EnableTransactionManagement注解来给我们容器加入了什么组件
在这里插入图片描述

3.1)@EnableTransactionManagement源码开始分析

org.springframework.transaction.annotation.EnableTransactionManagement

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
    
    /**
     * 指定使用什么代理模式(true为cglib代理,false 为jdk代理)
     * */
	boolean proxyTargetClass() default false;

    /**
     * 通知模式 是使用代理模式还是aspectj  我们一般使用Proxy
     * */
	AdviceMode mode() default AdviceMode.PROXY;

	int order() default Ordered.LOWEST_PRECEDENCE;
}

3.2)TransactionManagementConfigurationSelector

我们从3.1处的源码可以分析处他通过@Import导入了TransactionManagementConfigurationSelector组件
TransactionManagementConfigurationSelector源码分析
我们可以分析处向容器中导入了二个组件

  • 1)AutoProxyRegistrar
  • 2)ProxyTransactionManagementConfiguration
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

    /**
     * 往容器中添加组件 1) AutoProxyRegistrar
     *                2) ProxyTransactionManagementConfiguration
     * */
	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {  //因为我们配置的默认模式是PROXY
			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;
		}
	}

}
3.2.1)AutoProxyRegistrar

首先我们来分析AutoProxyRegistrar给我们容器中干了什么?
从源码分析出,AutoProxyRegistrar为我们容器注册了一个InfrastructureAdvisorAutoProxyCreator组件

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	private final Log logger = LogFactory.getLog(getClass());

	@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);
			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) { //默认模式是PROXY
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					if ((Boolean) proxyTargetClass) {
						AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
						return;
					}
				}
			}
		}
	}

}

	public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAutoProxyCreatorIfNecessary(registry, null);
	}
	
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	}
	
	private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        
        //判断容器中有没有org.springframework.aop.config.internalAutoProxyCreator名字的bean定义,
		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
				int requiredPriority = findPriorityForClass(cls);
				if (currentPriority < requiredPriority) {
					apcDefinition.setBeanClassName(cls.getName());
				}
			}
			return null;
		}
		
        
        //自己注册一个org.springframework.aop.config.internalAutoProxyCreator的组件
		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
		beanDefinition.setSource(source);
		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
		return beanDefinition;
	}
3.2.1.1)InfrastructureAdvisorAutoProxyCreator

我们从3.2.1可以分析出AutoProxyRegistrar会为我们容器中导入了一个叫InfrastructureAdvisorAutoProxyCreator的组件
①:我们来看下InfrastructureAdvisorAutoProxyCreator继承图
在这里插入图片描述
从继承图可看出,和之前AOP源码分析的AnnotationAwareAspectJAutoProxyCreator继承图基本相同。
由此可知,事物代理生成对象流程与AOP生成代理对象流程的套路是基本一样的。
在这里插入图片描述
分析InfrastructureAdvisorAutoProxyCreator 实现了如下的接口
①:实现了Aware接口(具体代表 BeanFactoryAware接口)
做了什么事情)
a:把我们的BeanFacotry容器设置到了InfrastructureAdvisorAutoProxyCreator组件中去
b: 创建了一个advisorRetrievalHelper组件 增强器检索工具

AbstractAutoProxyCreator 实现了BeanFactoryAware接口,但是马上又被AbstractAdvisorAutoProxyCreator给重写了;

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
public void setBeanFactory(BeanFactory beanFactory) {
	this.beanFactory = beanFactory;
}
//马上又被org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator重写了
public void setBeanFactory(BeanFactory beanFactory) {
	super.setBeanFactory(beanFactory);
	if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
		throw new IllegalArgumentException(
				"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
	}
	initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}

protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}

//但是AbstractAdvisorAutoProxyCreator类的initBeanFactory又被InfrastructureAdvisorAutoProxyCreator重写了
org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	super.initBeanFactory(beanFactory);
	this.beanFactory = beanFactory;
}

②:实现了我们的接口 InstantiationAwareBeanPostProcessor类型的后置处理器,为我们容器中做了什么事情
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInitialization
postProcessBeforeInstantiation方法

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (beanName == null || !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.
		if (beanName != null) {
			TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
			if (targetSource != null) {
				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;
	}
	

postProcessAfterInstantiation方法(没有做任何事情,直接返回)

public boolean postProcessAfterInstantiation(Object bean, String beanName) {
		return true;
	}

③:实现了我们的接口BeanPostProcessor类型的后置处理器,为我们容器中做了什么事情
postProcessBeforeInitialization方法没有做任何事情,直接返回

public Object postProcessBeforeInitialization(Object bean, String beanName) {
		return bean;
	}

postProcessAfterInitialization 为我们做了事情

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

3.3)ProxyTransactionManagementConfiguration

然后我们在来分析一下TransactionManagementConfigurationSelector 为我们还导入了一个类ProxyTransactionManagementConfiguration

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    
    
    /**
     * 为我我们容器中导入了 beanName为org.springframework.transaction.config.internalTransactionAdvisor
     * 类型为:BeanFactoryTransactionAttributeSourceAdvisor 的增强器
     * 
     * */
	@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;
	}

}
AnnotationTransactionAttributeSource

在这里插入图片描述

TransactionInterceptor

在这里插入图片描述

BeanFactoryTransactionAttributeSourceAdvisor

在这里插入图片描述

总结

画图总结,后续将具体的源码分析

Spring 源码探索 之 声明式事务源码解读(二)
在这里插入图片描述

相关学习路线

JAVA资深架构师成长路线->开源框架解读->Spring框架源码解读

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值