Spring事务(一)——切面的创建

目录

1. JDK如何控制事务

2. Spring事务

(1)@EnableTransactionManagement注解

a. AutoProxyRegistrar

b.  ProxyTransactionManagementConfiguration

(2)创建事务切面

(3)事务开启

a. 创建事务

b. 获取连接对象

c. 事务管理器


1. JDK如何控制事务

        我们先看一段代码:

public static void main(String[] args) {
        Connection connection = null;
        try {
            // 1.获取连接对象
            connection = ConnectionUtil.getConnection();
            // 2.开启事务的前奏,关闭自动提交
            connection.setAutoCommit(false);
            // 3.执行DML语句
            insertTest1(connection);
            insertTest2(connection);
            // 4.事务提交
            connection.commit();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                // 4.事务回滚
                connection.rollback();
                System.out.println("JDBC Transaction rolled back successfully");
            } catch (SQLException e1) {
                System.out.println("JDBC Transaction rolled back fail" + e1.getMessage());
            }
        } finally {
            if (connection != null) {
                try {
                    selectAll(connection);
                    // 5.连接关闭
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

        上面是JDK操作数据库、提交事务的流程,这是传统手艺,看懂了上面的代码有助于理解Spring事务。大致流程就是:

  • 开启事务
  • 执行被代理方法
  • 关闭事务

        判断是否在同一个事务的标准就是多个DML是否为同一个连接对象。

        Mysql的事务的提交方式默认为自动提交,如果有多个DML操作,每一个执行结束都会自动提交,所以要想多个DML操作在一个事务,必须将自动提交关闭(前提)。

2. Spring事务

        首先Spring的事务也是运用了AOP的思想,对需要Spring管理事务的Bean生成了代理对象,然后通过代理对象拦截目标方法的执行,在方法前后增加了事务的功能。

        我们知道,要实现AOP功能,必须有代理的入口类,那就是在类上加@EnableTransactionManagement注解,表示Spring对事务的支持,一般情况下该注解在配置类或SpringBoot的启动类上。

        在Bean的初始化过程中,会经过InfrastructureAdvisorAutoProxyCreator类的初始化及后面的方法,会判断当前当前Bean对象是否和BeanFactoryTransactionAttributeSourceAdvisor匹配,匹配逻辑为判断该Bean的类上是否存在@Transactional注解,或者类中的某个方法上是否存在@Transactional注解,如果存在则表示该Bean需要进行动态代理产生一个代理对象作为Bean对象。
        当该代理对象在执行某个方法时,会再次判断当前执行的方法是否和
BeanFactoryTransactionAttributeSourceAdvisor匹配,如果匹配则执行该Advisor中的
TransactionInterceptor的invoke()方法,大致流程为:

  • 创建一个数据库连接Connection;
  • 修改数据库连接的autocommit为false;
  • 把数据库连接放入threadLocal中(Map<DataSource,Connection>);
  • 执行MethodInvocation.proceed()方法,即执行业务方法;
  • 方法执行成功则提交,反之回滚。

(1)@EnableTransactionManagement注解

        Spring中新建事务就是新建一个数据库连接,通过配置@EnableTransactionManagement注解开启事务功能。

        该注解会@Import(TransactionManagementConfigurationSelector.class),TransactionManagementConfigurationSelector继承自AdciveModeImportSelector,AdciveModeImportSelector类实现了ImportSelector接口,重写了selectImports()方法:

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

	/**
	 * Returns {@link ProxyTransactionManagementConfiguration} or
	 * {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}
	 * and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},
	 * respectively.
	 */
	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
				// 默认是PROXY,就是在Spring容器中注册了这两个类AutoProxyRegistrar和ProxyTransactionManagementConfiguration类
				// AutoProxyRegistrar作用是开启AOP代理功能
				// ProxyTransactionManagementConfiguration作用是在Spring中注册了三个Bean:BeanFactoryTransactionAttributeSourceAdvisor、TransactionAttributeSource、TransactionInterceptor
				return new String[] {AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				// 表示不用动态代理激素,用ASPECTJ技术
				return new String[] {determineTransactionAspectClass()};
			default:
				return null;
		}
	}

        在selectImports()方法中,会在Spring容器中注册两个Bean:

  • AutoProxyRegistrar
  • ProxyTransactionManagementConfiguration

a. AutoProxyRegistrar

        先看第一个类:AutoProxyRegistrar

        它的作用是向Spring容器中注册InfrastructureAdvisorAutoProxyCreator类,这是事务的入口类,没有入口类无法生成代理。 而InfrastructureAdvisorAutoProxyCreator继承了AbstractAdvisorAutoProxyCreator,所以这个类的主要作用就是开启自动代理的作用,也就是一个BeanPostProcessor,会在初始化之后去寻找Advisor类型的Bean,并判断当前某个Bean是否有匹配的Advisor,是否需要利用动态代理产生一个代理对象。

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> annTypes = importingClassMetadata.getAnnotationTypes();
		for (String annType : annTypes) {
			AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
			if (candidate == null) {
				continue;
			}
			Object mode = candidate.get("mode");
			// proxyTargetClass属性是生成代理时copyFrom(),会把该属性copy到代理工厂
			Object proxyTargetClass = candidate.get("proxyTargetClass");
			if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
					Boolean.class == proxyTargetClass.getClass()) {
				candidateFound = true;
				if (mode == AdviceMode.PROXY) {
					// 注册事务的入口类————InfrastructureAdvisorAutoProxyCreator类
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					if ((Boolean) proxyTargetClass) {
						// 设置InfrastructureAdvisorAutoProxyCreator的proxyTargetClass为true
						AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
						return;
					}
				}
			}
		}

         会进入到registerAutoProxyCreatorIfNecessary():

        所属类:org.springframework.aop.config.AopConfigUtils

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

	@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
        // 就是注册InfrastructureAdvisorAutoProxyCreator类
		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	}

b.  ProxyTransactionManagementConfiguration

        再看第二个类:ProxyTransactionManagementConfiguration

        它是一个配置类,它又定义了另外三个bean:

  1. BeanFactoryTransactionAttributeSourceAdvisor:事务切面类,即Advisor;
  2. AnnotationTransactionAttributeSource:事务的切入点,相当于BeanFactoryTransactionAttributeSourceAdvisor中的Pointcut,用来判断当前类有无切面,并解析@Transactional注解属性;
  3. TransactionInterceptor:事务拦截器,相当于BeanFactoryTransactionAttributeSourceAdvisor中的Advice。
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

	// BeanFactoryTransactionAttributeSourceAdvisor就是一个实现事务功能的Advisor
	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {

		// 创建事务切面BeanFactoryTransactionAttributeSourceAdvisor
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		// 设置切面中处理事务属性的对象(TransactionAttributeSource用来解析@Transactional注解)
		advisor.setTransactionAttributeSource(transactionAttributeSource);
		// 设置切面的advice,即advisor中的事务拦截器
		advisor.setAdvice(transactionInterceptor);
		// 切面排序
		if (this.enableTx != null) {
			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		}
		return advisor;
	}

	// TransactionAttributeSource相当于解析@Transactional注解的工具类
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		// AnnotationTransactionAttributeSource(理解为注解属性资源类)中定义了一个Pointcut
		// AnnotationTransactionAttributeSource用来解析@Transactional注解,将注解信息封装成RuleBasedTransactionAttribute对象返回
		return new AnnotationTransactionAttributeSource();
	}

	// 定义事务拦截器,这个类很重要,事务的提交、回滚都会涉及到,会进入TransactionInterceptor.invoke()方法
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
		// 创建事务拦截器
		TransactionInterceptor interceptor = new TransactionInterceptor();
		// 把事务属性解析器设置到advice中
		interceptor.setTransactionAttributeSource(transactionAttributeSource);
		// 把事务管理器设置到advice中
		if (this.txManager != null) {
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}

}

(2)创建事务切面

       看一下事务切面类BeanFactoryTransactionAttributeSourceAdvisor:

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

	@Nullable
	private TransactionAttributeSource transactionAttributeSource;

	// 定义事务切面的Pointcut
	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
		@Override
		@Nullable
		protected TransactionAttributeSource getTransactionAttributeSource() {
			return transactionAttributeSource;
		}
	};

	public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
		this.transactionAttributeSource = transactionAttributeSource;
	}

	/**
	 * Set the {@link ClassFilter} to use for this pointcut.
	 * Default is {@link ClassFilter#TRUE}.
	 */
	public void setClassFilter(ClassFilter classFilter) {
		this.pointcut.setClassFilter(classFilter);
	}

	@Override
	public Pointcut getPointcut() {
		return this.pointcut;
	}
}

        它创建了TransactionAttributeSourcePointcut ,把TransactionAttributeSource传了进去,Pointcut必然有和ClassFilter和MethodMatcher,看一下TransactionAttributeSourcePointcut 类:

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

	protected TransactionAttributeSourcePointcut() {
		// TransactionAttributeSourceClassFilter判断类是否和TransactionAttributeSourcePointcut匹配,会调用到它的matches()方法
		setClassFilter(new TransactionAttributeSourceClassFilter());
	}

	// MethodMatcher接口的matches()方法,方法级别的匹配。
	// 用来判断方法是否和TransactionAttributeSourcePointcut匹配
	@Override
	public boolean matches(Method method, Class<?> targetClass) {
		TransactionAttributeSource tas = getTransactionAttributeSource();
		// 调用AbstractFallbackTransactionAttributeSource.getTransactionAttribute()方法
		// 只要方法上面能拿到事务属性就返回true,就会生成代理
		return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
	}

	/**
	 * Obtain the underlying TransactionAttributeSource (may be {@code null}).
	 * To be implemented by subclasses.
	 */
	@Nullable
	protected abstract TransactionAttributeSource getTransactionAttributeSource();


	/**
	 * {@link ClassFilter} that delegates to {@link TransactionAttributeSource#isCandidateClass}
	 * for filtering classes whose methods are not worth searching to begin with.
	 */
	private class TransactionAttributeSourceClassFilter implements ClassFilter {

		@Override
		public boolean matches(Class<?> clazz) {
			if (TransactionalProxy.class.isAssignableFrom(clazz) ||
					TransactionManager.class.isAssignableFrom(clazz) ||
					PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
				return false;
			}
			TransactionAttributeSource tas = getTransactionAttributeSource();
			// 看匹配方法org.springframework.transaction.annotation.AnnotationTransactionAttributeSource.isCandidateClass()
			return (tas == null || tas.isCandidateClass(clazz));
		}
	}

}

        它继承自StaticMethodMatcherPointcut,该类又继承StaticMethodMatcher、并实现了Pointcut接口,StaticMethodMatcher实现了MethodMatcher接口。

        理论上@Transactional注解也可以加在类上,但日常工作中很少这么使用,虽然引入了TransactionAttributeSourceClassFilter内部类,但是对类上的匹配却是不痛不痒,直接返回了true,最终会调到这里:

        所属类:org.springframework.core.annotation.AnnotationUtils

	public static boolean isCandidateClass(Class<?> clazz, String annotationName) {
		if (annotationName.startsWith("java.")) {
			return true;
		}
		if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
			return false;
		}
		return true;
	}

        真正的匹配是在方法级别,就是matches(),这是MethodMatcher接口的方法,只要方法上面能拿到事务属性就返回true,就会生成代理,调用TransactionAttributeSource.getTransactionAttribute()方法:

        所属类springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource

public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
		if (method.getDeclaringClass() == Object.class) {
			return null;
		}

		// First, see if we have a cached value.
		// 检查缓存,缓存里面保存的当前类和方法是否存在@Transactional注解
		Object cacheKey = getCacheKey(method, targetClass);
		TransactionAttribute cached = this.attributeCache.get(cacheKey);
		if (cached != null) {
			// Value will either be canonical value indicating there is no transaction attribute,
			// or an actual transaction attribute.
			if (cached == NULL_TRANSACTION_ATTRIBUTE) {
				return null;
			}
			else {
				return cached;
			}
		}
		else {
			// We need to work it out.
			// 解析并缓存结果,后面使用时就可以把方法上的注解信息直接拿到(核心代码)
			TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
			// Put it in the cache.
			if (txAttr == null) {
				this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
			}
			else {
				String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
				if (txAttr instanceof DefaultTransactionAttribute) {
					((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
				}
				if (logger.isTraceEnabled()) {
					logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
				}
				this.attributeCache.put(cacheKey, txAttr);
			}
			return txAttr;
		}
	}

        进入computeTransactionAttribute()获取方法上的@Transactional注解信息:

        所属类:transaction.interceptor.AbstractFallbackTransactionAttributeSource

protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
		// Don't allow no-public methods as required.
		// 如果是非public方法,则返回null,不会生成代理
		if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
			return null;
		}

		// The method may be on an interface, but we need attributes from the target class.
		// If the target class is null, the method will be unchanged.
		// 获取原始方法
		Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

		// First try is the method in the target class.
		// 检查方法上是否存在@Transactional注解,获取方法上面的@Transactional注解信息
		TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
		if (txAttr != null) {
			return txAttr;
		}

		// Second try is the transaction attribute on the target class.
		// 如果方法上没有@Transactional注解,再检查类上是否有
		txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
		if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
			return txAttr;
		}

		if (specificMethod != method) {
			// Fallback is to look at the original method.
			txAttr = findTransactionAttribute(method);
			if (txAttr != null) {
				return txAttr;
			}
			// Last fallback is the class of the original method.
			txAttr = findTransactionAttribute(method.getDeclaringClass());
			if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
				return txAttr;
			}
		}

		return null;
	}

        进入findTransactionAttribute()方法获取注解信息:

        所属类:org.springframework.transaction.annotation.AnnotationTransactionAttributeSource

	protected TransactionAttribute findTransactionAttribute(Method method) {
		return determineTransactionAttribute(method);
	}

         进入本类的determineTransactionAttribute():

	protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
		for (TransactionAnnotationParser parser : this.annotationParsers) {
			// 解析注解信息,SpringTransactionAnnotationParser.parseTransactionAnnotation()方法
			TransactionAttribute attr = parser.parseTransactionAnnotation(element);
			if (attr != null) {
				return attr;
			}
		}
		return null;
	}

        进入SpringTransactionAnnotationParser.parseTransactionAnnotation(),这个类是用来解析@Transactional注解的解析器。

        所属类:org.springframework.transaction.annotation.SpringTransactionAnnotationParser

	// 获取注解信息
	public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
		// 获取方法上面的注解属性
		AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
				element, Transactional.class, false, false);
		if (attributes != null) {
			// 解析@Transactional注解中的属性,并封装成对象
			return parseTransactionAnnotation(attributes);
		} else {
			return null;
		}
	}

         进入本类的parseTransactionAnnotation():

	protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
		// 解析@Transactional注解信息封装成RuleBasedTransactionAttribute对象
		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;
	}

        最终把注解属性封装成RuleBasedTransactionAttribute对象,如果没有@Transactional注解的方法,则会去解析类上面的@Transactional注解属性,原理和解析方法上的注解类似,流程就是先找方法,再找类

(3)事务开启

          接下来看代理逻辑:

        TransactionInterceptor就是事务的拦截器类,继承自TransactionAspectSupport类,并实现了MethodInterceptor接口。

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

	public TransactionInterceptor(TransactionManager ptm, TransactionAttributeSource tas) {
		setTransactionManager(ptm);
		setTransactionAttributeSource(tas);
	}

	@Deprecated
	public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) {
		setTransactionManager(ptm);
		setTransactionAttributeSource(tas);
	}

	@Deprecated
	public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) {
		setTransactionManager(ptm);
		setTransactionAttributes(attributes);
	}

        当某个类中存在@Transactional注解时,到时就产生一个代理对象作为Bean,代理对象在执行某个方法时,最终就会进入到TransactionInterceptor的invoke()方法。

        看TransactionInterceptor的invoke()方法:

	public Object invoke(MethodInvocation invocation) throws Throwable {
		// Work out the target class: may be {@code null}.
		// The TransactionAttributeSource should be passed the target class
		// as well as the method, which may be from an interface.
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

		// Adapt to TransactionAspectSupport's invokeWithinTransaction...
		// 执行后续的Interceptor,及代理的方法invocation::proceed
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}

        当用代理对象调用的时候,就会进入invokeWithinTransaction()方法:

        所属类:org.springframework.transaction.interceptor.TransactionAspectSupport

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

		// If the transaction attribute is null, the method is non-transactional.
		// 获取事务属性源对象,TransactionAttribute类相当于@Transactional注解信息的一个封装类
		TransactionAttributeSource tas = getTransactionAttributeSource();
		// 通过源对象获取@Transactional注解中的配置信息
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		// 获取Spring容器中定义的TransactionManager事务管理器对象
		final TransactionManager tm = determineTransactionManager(txAttr);

		// ReactiveTransactionSupportManager用的少,它执行方式是响应式的,原理流程和普通的是一样的
		if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
			ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
				if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {
					throw new TransactionUsageException(
							"Unsupported annotated transaction on suspending function detected: " + method +
							". Use TransactionalOperator.transactional extensions instead.");
				}
				ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
				if (adapter == null) {
					throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
							method.getReturnType());
				}
				return new ReactiveTransactionSupport(adapter);
			});
			return txSupport.invokeWithinTransaction(
					method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
		}

		// 把tm强制转换为PlatformTransactionManager,所以我们在定义时须定义为PlatformTransactionManager类型
		PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
		// 获取joinpoint,joinpoint的唯一标识,就是当前执行的方法名称(标注了@Transactionl的方法名)
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
		// 处理声明式事务
		if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			// 开启事务
			// TransactionInfo表示一个逻辑事务,比如两个逻辑事务属于同一个物理事务(重要程度:5)
			TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

			Object retVal;
			try {
				// This is an around advice: Invoke the next interceptor in the chain.
				// This will normally result in a target object being invoked.
				// 火炬传递,调用被代理对象中的被代理方法(原始方法)
				// 执行TransactionInterceptor.invoke()最后一行匿名对象方法invocation::proceed
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// target invocation exception
				// 回滚事务
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				// 清空线程中的transactionInfo
				cleanupTransactionInfo(txInfo);
			}

			if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
				// Set rollback-only in case of Vavr failure matching our rollback rules...
				TransactionStatus status = txInfo.getTransactionStatus();
				if (status != null && txAttr != null) {
					retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
				}
			}
			// 提交事务
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}

		// 编程式事务
		else {
			Object result;
			final ThrowableHolder throwableHolder = new ThrowableHolder();

			// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
			try {
				result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
					TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
					try {
						Object retVal = invocation.proceedWithInvocation();
						if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
							// Set rollback-only in case of Vavr failure matching our rollback rules...
							retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
						}
						return retVal;
					}
					catch (Throwable ex) {
						if (txAttr.rollbackOn(ex)) {
							// A RuntimeException: will lead to a rollback.
							if (ex instanceof RuntimeException) {
								throw (RuntimeException) ex;
							}
							else {
								throw new ThrowableHolderException(ex);
							}
						}
						else {
							// A normal return value: will lead to a commit.
							throwableHolder.throwable = ex;
							return null;
						}
					}
					finally {
						cleanupTransactionInfo(txInfo);
					}
				});
			}

        在容器启动的时候,就会把AnnotationTransactionAttributeSource类设置到transactionAttributeSource属性中,所以上面方法中的代码:

    TransactionAttributeSource tas = getTransactionAttributeSource()

        就可以拿到属性解析对象,接着再获取事务管理器:

	protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
		// Do not attempt to lookup tx manager if no tx attributes are set
		if (txAttr == null || this.beanFactory == null) {
			return getTransactionManager();
		}

		String qualifier = txAttr.getQualifier();
		if (StringUtils.hasText(qualifier)) {
			return determineQualifiedTransactionManager(this.beanFactory, qualifier);
		}
		else if (StringUtils.hasText(this.transactionManagerBeanName)) {
			return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
		}
		else {
			// 从advice中获取事务管理器
			TransactionManager defaultTransactionManager = getTransactionManager();
			if (defaultTransactionManager == null) {
				defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
				if (defaultTransactionManager == null) {
					// 从Spring容器获取事务管理器,获取实现TransactionManager接口的实例
					defaultTransactionManager = this.beanFactory.getBean(TransactionManager.class);
					this.transactionManagerCache.putIfAbsent(
							DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
				}
			}
			return defaultTransactionManager;
		}
	}

        所以,可以自定义事务管理器,PlatformTransactionManager实现TransactionManager接口,一般就是采用这种方式:

    @Bean
    public PlatformTransactionManager annotationDrivenTransactionManager(DataSource dataSource) {
        DataSourceTransactionManager dtm = new DataSourceTransactionManager();
        dtm.setDataSource(dataSource);
        return dtm;
    }

         接下来进入开启(创建)事务的核心方法createTransactionIfNecessary():

        所属类:org.springframework.transaction.interceptor.TransactionAspectSupport

	protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {

		// If no name specified, apply method identification as transaction name.
		// 把方法名作为一个事务名称
		if (txAttr != null && txAttr.getName() == null) {
			txAttr = new DelegatingTransactionAttribute(txAttr) {
				@Override
				public String getName() {
					return joinpointIdentification;
				}
			};
		}

		// 每个逻辑事务都会创建一个TransactionStatus,但是TransactionStatus中有一个属性代表当前逻辑事务底层的物理事务不是最新的
		TransactionStatus status = null;
		if (txAttr != null) {
			if (tm != null) {
				// 开启事务*****
				status = tm.getTransaction(txAttr);
			}
			else {
				if (logger.isDebugEnabled()) {
					logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
							"] because no transaction manager has been configured");
				}
			}
		}
		// 把事务状态和事务属性等信息封装成一个TransactionInfo对象,表示得到了一个事务,可能是新创建的事务,也可能是拿到已有的
		return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
	}

a. 创建事务

        进入tm.getTransaction(txAttr)开启事务方法:

        所属类:org.springframework.transaction.support.AbstractPlatformTransactionManager

public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException {

		// Use defaults if no transaction definition given.
		TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());

		// 得到一个DataSourcetranctionObject类(就是事务对象)****
		Object transaction = doGetTransaction();
		boolean debugEnabled = logger.isDebugEnabled();

		// 判断之前是否已存在事务对象(第一次进来为空)
		if (isExistingTransaction(transaction)) {
			// Existing transaction found -> check propagation behavior to find out how to behave.
			// 如果不是第一次进来, 则走这里,表示之前已开启事务,则为现有事务创建TransactionStatus。
			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.
		// 若事务属性式为PROPAGATION_MANDATORY,表示必须运行在事务中,没有就抛出异常
		if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		/**
		 * 如果存在事务,以下三种传播机制都会进入相同的处理逻辑
		 * PROPAGATION_REQUIRED:存在事务就加入到当前的事务,没有就新开一个
		 * PROPAGATION_REQUIRES_NEW:新开一个事务,若当前存在事务就挂起当前事务
		 * PROPAGATION_NESTED: 表示如果当前正有一个事务在运行中,则该方法应该运行在一个嵌套的事务中,
		 * 被嵌套的事务可以独立于封装事务进行提交或者回滚(保存点),如果封装事务不存在,行为就像PROPAGATION_REQUIRES_NEW
		 */
		else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			// 没有事务需要挂起,不过TransactionSynchronization有可能需要挂起
			// SuspendedResources表示当前线程被挂起的资源持有对象(数据库连接、TransactionSynchronization)
			/**
			 * 挂起当前事务,SuspendedResources表示当前线程被挂起的资源持有对象(数据库连接、TransactionSynchronization)
			 * 逻辑走到这里,经过了上面的isExistingTransaction(transaction)可以断定当前不存在事务,所有这里挂起当前事务传递一个null进去
			 */
			SuspendedResourcesHolder suspendedResources = suspend(null);
			if (debugEnabled) {
				logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
			}
			try {
				// 开启新事务,事务中就会有数据库连接了,并且isTransactionActive为true
				// 新创建一个事务状态TransactionStatus对象,该对象保存了很多信息,包括被挂起的资源(重要程度:5)
				return startTransaction(def, transaction, debugEnabled, suspendedResources);
			}
			catch (RuntimeException | Error ex) {
				resume(null, suspendedResources);
				throw ex;
			}
		}
		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);
		}
	}

b. 获取连接对象

        先看doGetTransaction(),获取数据源事务对象,会去ThreadLocal中拿连接对象:

        所属类:org.springframework.jdbc.datasource.DataSourceTransactionManager

	protected Object doGetTransaction() {
		// 创建一个事务对象
		DataSourceTransactionObject txObject = new DataSourceTransactionObject();
		txObject.setSavepointAllowed(isNestedTransactionAllowed());
		// 根据DataSource对象去ThreadLocal中拿连接对象ConnectionHolder,第一次进来拿的时候是空的
		ConnectionHolder conHolder =
				(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
		txObject.setConnectionHolder(conHolder, false);
		return txObject;
	}

        DataSourceTransactionObject封装了与连接对象相关的属性,如是否只读、隔离级别、是否按回滚点进行回滚。

        ConnectionHolder是DataSourceTransactionObject父类JdbcTransactionObjectSupport的属性,是数据库连接的封装类。会从TransactionSynchronizationManager(数据源管理器)中拿到连接对象:

	public static Object getResource(Object key) {
		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
		Object value = doGetResource(actualKey);
		if (value != null && logger.isTraceEnabled()) {
			logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" +
					Thread.currentThread().getName() + "]");
		}
		return value;
	}

        进入doGetResource(),从数据源管理器中获取数据源对象,也就是连接池对象:

        所属类:org.springframework.transaction.support.TransactionSynchronizationManager

private static Object doGetResource(Object actualKey) {
		// resources是ThreadLocal包装的Map,用来缓存资源的,比如缓存当前线程中由某个DataSource所创建的数据库连接
		Map<Object, Object> map = resources.get();
		if (map == null) {
			return null;
		}

		// 获取DataSource对象所对应的数据库连接对象
		Object value = map.get(actualKey);
		// Transparently remove ResourceHolder that was marked as void...
		if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
			map.remove(actualKey);
			// Remove entire ThreadLocal if empty...
			if (map.isEmpty()) {
				resources.remove();
			}
			value = null;
		}
		return value;
	}

         连接对象是从ThreadLocal中获取的:

	// key为DataSource对象,value为ConnectionHolder对象
	private static final ThreadLocal<Map<Object, Object>> resources =
			new NamedThreadLocal<>("Transactional resources");

        dataSource是从哪来的,就是启动的时候设置进去的:

    @Bean
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        DataSourceTransactionManager dtm = new DataSourceTransactionManager();
        // 就是这里,把DataSource传进去
        dtm.setDataSource(dataSource());
        return dtm;
    }

        DataSource就是自定义配置的:

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl("jdbc:mysql://192.168.1.200:3306/test?useUnicode=true&useSSL=false");
        dataSource.setUsername("root");
        dataSource.setPassword("huanbao");
        return dataSource;
    }

c. 事务管理器

        对于事务管理器,补充一点,前面提到的事务配置类ProxyTransactionManagementConfiguration.transactionInterceptor()方法中的事务管理器this.txManager哪来的?        

        ProxyTransactionManagementConfiguration配置类继承自AbstractTransactionManagementConfiguration类,是父类中定义的。

@Configuration
public abstract class AbstractTransactionManagementConfiguration implements ImportAware {

	@Nullable
	protected AnnotationAttributes enableTx;

	/**
	 * Default transaction manager, as configured through a {@link TransactionManagementConfigurer}.
	 */
	@Nullable
	protected TransactionManager txManager;


	@Override
	public void setImportMetadata(AnnotationMetadata importMetadata) {
		this.enableTx = AnnotationAttributes.fromMap(
				importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
		if (this.enableTx == null) {
			throw new IllegalArgumentException(
					"@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
		}
	}

    // 支持自定义,依赖注入
	@Autowired(required = false)
	void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
		if (CollectionUtils.isEmpty(configurers)) {
			return;
		}
		if (configurers.size() > 1) {
			throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
		}
        // 拿到参数中传进来的某一个
		TransactionManagementConfigurer configurer = configurers.iterator().next();
        // 就可以获取到自定义的事务管理器
		this.txManager = configurer.annotationDrivenTransactionManager();
	}

        支持自定义事务管理器,如: 

@Component
public class TransactionManagementConfigurerBean implements TransactionManagementConfigurer {

    @Autowired
    private DataSource dataSource;

    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        DataSourceTransactionManager dtm = new DataSourceTransactionManager();
        dtm.setDataSource(dataSource);
        return dtm;
    }
}

        到此,事务已经创建好了,接下来就是事务提交、回滚和传播属性的相关内容。

        由于内容较多,为了方便阅读,分成了三个章节,欢迎进入~~

猜你喜欢

转载自blog.csdn.net/qq_40213907/article/details/120777951
今日推荐