spirng事务原理

spring封装的事务框架很好用,在bean的方法上标注@Transactional后,就能开始spring支持的事务了。

java 复制代码
public @interface Transactional {
//指定事务管理器
	@AliasFor("transactionManager")
	String value() default "";
//指定事务管理器
	@AliasFor("value")
	String transactionManager() default "";
//事务传播性,多个事务方法嵌套时设置事务生成的方式
	Propagation propagation() default Propagation.REQUIRED;
//事务隔离性
	Isolation isolation() default Isolation.DEFAULT;
//事务方法超时时间
	int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
//是否只读
	boolean readOnly() default false;
//支持回滚的异常
	Class<? extends Throwable>[] rollbackFor() default {};
	String[] rollbackForClassName() default {};
//不会回滚的异常
	Class<? extends Throwable>[] noRollbackFor() default {};
	String[] noRollbackForClassName() default {};
}

现在开始看spring事务的源码,spring启动时会读取spring.factories配置的自动装配类,就会读到TransactionAutoConfiguration,其内部类CglibAutoProxyConfiguration的注解@EnableTransactionManagement(proxyTargetClass = true)导入事务配置类,其中的@Import(TransactionManagementConfigurationSelector.class)会导入TransactionManagementConfigurationSelector组件,此组件会注册两个重要的组件AutoProxyRegistrarProxyTransactionManagementConfigurationAutoProxyRegistrar用来注册生成事务bean的代理对象的组件InfrastructureAdvisorAutoProxyCreatorProxyTransactionManagementConfiguration会创建三个重要的bean:

  1. BeanFactoryTransactionAttributeSourceAdvisor是通知器,判断bean是否需要生成代理对象,即是否存在@Transactional注解
  2. TransactionAttributeSource读取@Transactional注解的属性
  3. TransactionInterceptor拦截器,生成代理对象后用来拦截原始bean的方法

先看spring启动阶段InfrastructureAdvisorAutoProxyCreator创建代理对象的源码,其继承的抽象父类AbstractAutoProxyCreator.java实现的postProcessBeforeInstantiation方法会收集容器中的增强器Advisor,刚才创建的BeanFactoryTransactionAttributeSourceAdvisor会从容器中被找出来。每个bean实例化后,会通过SmartInstantiationAwareBeanPostProcessor.java接口的getEarlyBeanReference方法判断是否需要生成代理bean。

java 复制代码
	public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
        //获取class中所有Method
		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;
				}
			}
		}
    //判断是否存在@Transactional
	public boolean matches(Method method, Class<?> targetClass) {
		TransactionAttributeSource tas = getTransactionAttributeSource();
		return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
	}

TransactionAttributeSource在spring启动时用来判断是否需要生成事务代理对象,同时会解析@Transactional注解,生成TransactionAttribute接口表示事务相关属性。

java 复制代码
	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"));

		List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
		for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
			rollbackRules.add(new RollbackRuleAttribute(rbRule));
		}
		for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
			rollbackRules.add(new RollbackRuleAttribute(rbRule));
		}
		for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
			rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
		}
		for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
			rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
		}
		rbta.setRollbackRules(rollbackRules);

		return rbta;
	}

发现bean的class中存在事务注解后,就会通过cglib生成bean的代理对象。

java 复制代码
	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		ProxyFactory proxyFactory = new ProxyFactory();
......  //设置增强器
		proxyFactory.addAdvisors(advisors);
......
		return proxyFactory.getProxy(getProxyClassLoader());
	}

	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
		}

		try {
......

			// Configure CGLIB Enhancer...
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
            //设置代理类
			enhancer.setSuperclass(proxySuperClass);
            //设置代理接口
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));

			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			// fixedInterceptorMap only populated at this point, after getCallbacks call above
			enhancer.setCallbackFilter(new ProxyCallbackFilter(
					this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
			enhancer.setCallbackTypes(types);

			// Generate the proxy class and create a proxy instance.
			return createProxyClassAndInstance(enhancer, callbacks);
		}
......
	}

通过代理对象调用方法时,就会对原来bean的方法调用进行拦截,拦截的行为在invokeWithinTransaction方法中。

java 复制代码
	public Object invoke(MethodInvocation invocation) throws Throwable {
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}

拦截方法中首先获取事务属性、事务管理器,通过事务管理器获取内置的数据源DataSource获取数据库连接,同时开启事务,设置事务属性,例如隔离性、是否自动提交、是否只读,然后反射执行目标方法,发生异常时判断是否回滚,没有异常则提交事务。

java 复制代码
	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {

		TransactionAttributeSource tas = getTransactionAttributeSource();
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		final TransactionManager tm = determineTransactionManager(txAttr);

		PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

		if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
			// 声明事务
			TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

			Object retVal;
			try {
				// 反射调用目标方法
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// 异常处理
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
                //清除数据
				cleanupTransactionInfo(txInfo);
			}
            //没有发生异常则提交事务
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}

开始事务时,通过线程变量获取ConnectionHolder,判断当前方法是否已经在事务中,如果已经存在则handleExistingTransaction处理现有事务;否则根据事务传播性开启事务。

java 复制代码
	public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException {
......//事务已存在
		if (isExistingTransaction(transaction)) {
			// Existing transaction found -> check propagation behavior to find out how to behave.
			return handleExistingTransaction(def, transaction, debugEnabled);
		}

		// Check definition settings for new transaction.
		if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
		}

		// No existing transaction found -> check propagation behavior to find out how to proceed.
		if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			SuspendedResourcesHolder suspendedResources = suspend(null);

			try {
                //开启事务
				return startTransaction(def, transaction, debugEnabled, suspendedResources);
			}
......
		}
		else {
			// Create "empty" transaction: no actual transaction, but potentially synchronization.
			if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
				logger.warn("Custom isolation level specified but no actual transaction initiated; " +
						"isolation level will effectively be ignored: " + def);
			}
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
		}
	}

根据事务传播性处理方法已有的事务,并且可以校验现有事务的隔离性和是否只读。

java 复制代码
	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) {
			if (debugEnabled) {
				logger.debug("Suspending current transaction");
			}
			Object suspendedResources = suspend(transaction);
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(
					definition, null, false, newSynchronization, debugEnabled, suspendedResources);
		}
        //即便已有事务也会开启新的事务
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
			if (debugEnabled) {
				logger.debug("Suspending current transaction, creating new transaction with name [" +
						definition.getName() + "]");
			}
			SuspendedResourcesHolder suspendedResources = suspend(transaction);
			try {
				return startTransaction(definition, transaction, debugEnabled, suspendedResources);
			}
			catch (RuntimeException | Error beginEx) {
				resumeAfterBeginException(transaction, suspendedResources, beginEx);
				throw beginEx;
			}
		}
        //嵌套事务
		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 (debugEnabled) {
				logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
			}
            //能够创建保存点
			if (useSavepointForNestedTransaction()) {
				DefaultTransactionStatus status =
						prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
				status.createAndHoldSavepoint();
				return status;
			}
			else {//开始新的事务
				return startTransaction(definition, transaction, debugEnabled, null);
			}
		}
        //检验现有事务
		if (isValidateExistingTransaction()) {
            //如果当前事务隔离性和已有事务的隔离性不一致
			if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
				Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
				if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
					Constants isoConstants = DefaultTransactionDefinition.constants;
					throw new IllegalTransactionStateException("Participating transaction with definition [" +
							definition + "] specifies isolation level which is incompatible with existing transaction: " +
							(currentIsolationLevel != null ?
									isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
									"(unknown)"));
				}
			}
            //外层事务只读,但是当前事务非只读
			if (!definition.isReadOnly()) {
				if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
					throw new IllegalTransactionStateException("Participating transaction with definition [" +
							definition + "] is not marked as read-only but existing transaction is");
				}
			}
		}
		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
	}

开启事务之前需要先记录现有事务的属性,通过SuspendedResourcesHolder去封装现有事务的属性。

java 复制代码
	protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
		if (TransactionSynchronizationManager.isSynchronizationActive()) {
			List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
			try {
				Object suspendedResources = null;
				if (transaction != null) {
					suspendedResources = doSuspend(transaction);
				}
				String name = TransactionSynchronizationManager.getCurrentTransactionName();
				TransactionSynchronizationManager.setCurrentTransactionName(null);
                //是否只读
				boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
				TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
                //隔离性
				Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
				TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
				boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
				TransactionSynchronizationManager.setActualTransactionActive(false);
				return new SuspendedResourcesHolder(
						suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
			}
			catch (RuntimeException | Error ex) {
				// doSuspend failed - original transaction is still active...
				doResumeSynchronization(suspendedSynchronizations);
				throw ex;
			}
		}
......
	}

开启事务时先从数据库连接池中获取连接,然后为连接设置隔离性、是否只读,记录来自注解的超时时间。

java 复制代码
	protected void doBegin(Object transaction, TransactionDefinition definition) {
.....
            //从数据库连接池中获取连接
			txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
			con = txObject.getConnectionHolder().getConnection();
            //设置隔离性、是否只读
			Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
			txObject.setPreviousIsolationLevel(previousIsolationLevel);
			txObject.setReadOnly(definition.isReadOnly());
            //关闭自动提交
			if (con.getAutoCommit()) {
				txObject.setMustRestoreAutoCommit(true);
				if (logger.isDebugEnabled()) {
					logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
				}
				con.setAutoCommit(false);
			}
            //如果只读就执行 SET TRANSACTION READ ONLY
			prepareTransactionalConnection(con, definition);
			txObject.getConnectionHolder().setTransactionActive(true);
            //设置超时
			int timeout = determineTimeout(definition);
			if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
				txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
			}

			if (txObject.isNewConnectionHolder()) {
				TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
			}
		}
......
	}

最后如果发生异常后,判断异常类型是否事务支持回滚的异常类型,不支持回滚的话就commit提交,底层还是jdbc操作。

java 复制代码
	protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
		if (txInfo != null && txInfo.getTransactionStatus() != null) {
			if (logger.isTraceEnabled()) {
				logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
						"] after exception: " + ex);
			}
			if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
				try {
					txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
				}
				catch (TransactionSystemException ex2) {
					logger.error("Application exception overridden by rollback exception", ex);
					ex2.initApplicationException(ex);
					throw ex2;
				}
				catch (RuntimeException | Error ex2) {
					logger.error("Application exception overridden by rollback exception", ex);
					throw ex2;
				}
			}
			else {
				// We don't roll back on this exception.
				// Will still roll back if TransactionStatus.isRollbackOnly() is true.
				try {
					txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
				}
				catch (TransactionSystemException ex2) {
					logger.error("Application exception overridden by commit exception", ex);
					ex2.initApplicationException(ex);
					throw ex2;
				}
				catch (RuntimeException | Error ex2) {
					logger.error("Application exception overridden by commit exception", ex);
					throw ex2;
				}
			}
		}
	}

总结下,spring用代理拦截方法调用,配合 ThreadLocal 保存事务上下文,按照传播规则决定是否开启/挂起事务,在方法结束时根据执行结果去调用数据库的 commit / rollback,更多请关注微信公众号 葡萄开源

相关推荐
往事随风去4 小时前
Redis的内存淘汰策略(Eviction Policies)有哪些?
redis·后端·算法
秦禹辰4 小时前
宝塔面板安装MySQL数据库并通过内网穿透工具实现公网远程访问
开发语言·后端·golang
lypzcgf4 小时前
Coze源码分析-资源库-删除插件-后端源码-应用和领域服务层
后端·go·coze·coze插件·coze源码分析·智能体平台·ai应用平台
lssjzmn4 小时前
Spring Web 异步响应实战:从 CompletableFuture 到 ResponseBodyEmitter 的全链路优化
java·前端·后端·springboot·异步·接口优化
shark_chili4 小时前
程序员必知的底层原理:CPU缓存一致性与MESI协议详解
后端
愿时间能学会宽恕5 小时前
SpringBoot后端开发常用工具详细介绍——SpringSecurity认证用户保证安全
spring boot·后端·安全
CodeSheep5 小时前
稚晖君又开始摇人了,有点猛啊!
前端·后端·程序员
小宁爱Python5 小时前
Django 从环境搭建到第一个项目
后端·python·django
uzong5 小时前
深入浅出:画好技术图
后端·架构