1. 程式人生 > 其它 >【Srping】事務的執行原理(一)

【Srping】事務的執行原理(一)

在使用事務的時候需要新增@EnableTransactionManagement註解來開啟事務,那麼就從@EnableTransactionManagement入手檢視一下事務的執行原理。

@EnableTransactionManagement

  1. Spring事務底層是通過AOP來完成的,而Spring AOP基於動態代理實現,可以看到mode方法預設返回了PROXY代理模式,我們只需關注代理模式下的執行流程即可
  2. 使用@Import匯入了TransactionManagementConfigurationSelector
@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 Ordered.LOWEST_PRECEDENCE;
}

TransactionManagementConfigurationSelector

在selectImports方法中可以看到對模式進行了判斷:

  1. 如果是基於代理模式,返回AutoProxyRegistrar和ProxyTransactionManagementConfiguration類
  2. 如果是基於ASPECTJ,呼叫determineTransactionAspectClass方法

Spring預設使用的是代理模式,所以接下來看下AutoProxyRegistrar和ProxyTransactionManagementConfiguration裡面都有什麼。

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
                                // 如果基於代理模式
				return new String[] {AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
                                // 如果基於ASPECTJ
				return new String[] {determineTransactionAspectClass()};
			default:
				return null;
		}
	}

	private String determineTransactionAspectClass() {
		return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
				TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
				TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
	}

}

AutoProxyRegistrar

AutoProxyRegistrar實現了ImportBeanDefinitionRegistrar介面,ImportBeanDefinitionRegistrar可以向容器中註冊Bean,跟著registerBeanDefinitions方法看下它會向容器中註冊什麼樣的bean:

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;
			}
			Object mode = candidate.get("mode");
			Object proxyTargetClass = candidate.get("proxyTargetClass");
			if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
					Boolean.class == proxyTargetClass.getClass()) {
				candidateFound = true;
				if (mode == AdviceMode.PROXY) {
                                        // 呼叫AopConfigUtils的registerAutoProxyCreatorIfNecessary向容器中註冊bean
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					if ((Boolean) proxyTargetClass) {
						AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
						return;
					}
				}
			}
		}
		if (!candidateFound && logger.isInfoEnabled()) {
			String name = getClass().getSimpleName();
			logger.info(String.format("%s was imported but no annotations were found " +
					"having both 'mode' and 'proxyTargetClass' attributes of type " +
					"AdviceMode and boolean respectively. This means that auto proxy " +
					"creator registration and configuration may not have occurred as " +
					"intended, and components may not be proxied as expected. Check to " +
					"ensure that %s has been @Import'ed on the same class where these " +
					"annotations are declared; otherwise remove the import of %s " +
					"altogether.", name, name, name));
		}
	}
}

AopConfigUtils

在AopConfigUtils中一共有三種自動代理建立器:

  1. InfrastructureAdvisorAutoProxyCreator
  2. AspectJAwareAdvisorAutoProxyCreator
  3. AnnotationAwareAspectJAutoProxyCreator

在registerAutoProxyCreatorIfNecessary方法中,可以看到事務使用的是InfrastructureAdvisorAutoProxyCreator型別的建立器:

public abstract class AopConfigUtils {

	/**
	 * 自動代理建立器BeanName
	 */
	public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
			"org.springframework.aop.config.internalAutoProxyCreator";

	/**
	 * 所有的自動代理建立器集合
	 */
	private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);

	static {
		// 初始化
		APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
		APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class); // AspectJ
		APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class); // 註解
	}

        // AutoProxyRegistrar中呼叫的registerAutoProxyCreatorIfNecessary方法
	@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
	        // 會呼叫下面那個registerAutoProxyCreatorIfNecessary方法
		return registerAutoProxyCreatorIfNecessary(registry, null);
	}
	
	@Nullable
	public static BeanDefinition registerAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {
		// 呼叫registerOrEscalateApcAsRequired進行註冊,這裡傳入的是InfrastructureAdvisorAutoProxyCreator型別的
		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	}

@Nullable
	private static BeanDefinition registerOrEscalateApcAsRequired(
			Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
                // 判斷容器中是否已經包含代理建立器
		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;
		}
                // 建立RootBeanDefinition
		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
                // 設定source
		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;
	}
}

總結

AutoProxyRegistrar實現ImportBeanDefinitionRegistrar是為了向容器中註冊代理建立器,事務預設使用的是InfrastructureAdvisorAutoProxyCreator型別的。

ProxyTransactionManagementConfiguration

1. AOP概念

Advice通知:定義在切點上需要執行什麼樣的操作

PointCut切點:定義在哪些方法上使用通知

Advisor:Advice和Pointcut加起來組成了Advisor

2. 事務中的Advisor

我們已經知道事務是基於AOP實現的,在transactionAdvisor方法中可以看到建立了Advisor,然後設定了事務屬性TransactionAttributeSource和事務攔截器TransactionInterceptor:

  • TransactionAttributeSource,從名字上可以看出是和事務的屬性設定相關的
  • TransactionInterceptor事務攔截器相當於Advice通知
  • BeanFactoryTransactionAttributeSourceAdvisor是Advisor

Advisor由Advice和PointCut組成,現在Advice已經有了,接下來看下Pointcut在哪裡。

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

        @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
                // 建立Advisor
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
                // 設定TransactionAttributeSource,型別為AnnotationTransactionAttributeSource
		advisor.setTransactionAttributeSource(transactionAttributeSource);
                // 設定事務攔截器,相當於Advice
		advisor.setAdvice(transactionInterceptor);
		if (this.enableTx != null) {
			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		}
		return advisor;
	}

        @Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
                // 建立AnnotationTransactionAttributeSource
		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;
	}
}

BeanFactoryTransactionAttributeSourceAdvisor

BeanFactoryTransactionAttributeSourceAdvisor繼承關係如下:

除了繼承父類的屬性和方法,它自己還有兩個成員變數:

  1. transactionAttributeSource,實際傳入的是AnnotationTransactionAttributeSource型別的物件
  2. TransactionAttributeSourcePointcut型別的切點pointcut
    • 切點在例項化時實現了getTransactionAttributeSource方法,返回了transactionAttributeSource,後面的方法中需要呼叫此方法獲取transactionAttributeSource

由上面的分析可知,在建立BeanFactoryTransactionAttributeSourceAdvisor的時候,設定了TransactionInterceptor和TransactionAttributeSource,TransactionInterceptor相當於Advice,而這裡我們看到了它還有一個TransactionAttributeSourcePointcut切點:

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

	@Nullable
	private TransactionAttributeSource transactionAttributeSource; // 實際傳入的是AnnotationTransactionAttributeSource型別的

        // 建立切點
	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
    
                // 實現了getTransactionAttributeSource方法,返回的是AnnotationTransactionAttributeSource
		@Override
		@Nullable
		protected TransactionAttributeSource getTransactionAttributeSource() {
			return transactionAttributeSource;
		}
	};

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

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

}

TransactionAttributeSourcePointcut

TransactionAttributeSourcePointcut是一個切點,它的繼承關係如下:

PointcutMethodMatcher

Pointcut介面中定義了兩個方法:

  1. 獲取ClassFilter,ClassFilter是一個介面,裡面定義了matches方法,檢查切點是否與類匹配
  2. 獲取MethodMatcher,它也是一個介面,並且定義了matches方法,檢查切點是否與方法匹配
public interface Pointcut {

	/**
	 * 返回類過濾器ClassFilter
	 */
	ClassFilter getClassFilter();

	/**
	 * 返回MethodMatcher
	 */
	MethodMatcher getMethodMatcher();

}

public interface MethodMatcher {

	/**
	 * 檢查方法是否匹配pointcut
	 */
	boolean matches(Method method, Class<?> targetClass);

	/**
	 * 檢查方法是否匹配pointcut
	 */
	boolean matches(Method method, Class<?> targetClass, Object... args);

}

@FunctionalInterface
public interface ClassFilter {

	/**
	 * 檢查類是否與pointcut匹配
	 */
	boolean matches(Class<?> clazz);

}

TransactionAttributeSourcePointcut是Pointcut和MethodMatcher的子類:

  1. 在建構函式中設定了ClassFilter,型別為TransactionAttributeSourceClassFilter,它是TransactionAttributeSourcePointcut的一個內部類,實現了ClassFilter介面中定義的matches方法,檢查pointcut與類是否匹配:
    • 如果是TransactionalProxy、PlatformTransactionManager或者PersistenceExceptionTranslator的子類,則不匹配
    • 獲取TransactionAttributeSource,呼叫它的isCandidateClass方法判斷是否匹配
  2. 實現了MethodMatcher介面中定義的matches方法,檢查pointcut是否匹配當前的方法
    • 獲取TransactionAttributeSource判斷是否為空,如果不為空則呼叫getTransactionAttribute獲取事務屬性,TransactionAttributeSource為空,或者從TransactionAttributeSource獲取到的事務屬性不為空都會返回true

所以一個方法執行時開啟事務,需要滿足兩個條件,當前的方法和類都需要與事務的pointcut匹配,對應的方法分別是MethodMatcher的matches和ClassFilter的matches方法。

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

  
	protected TransactionAttributeSourcePointcut() {
                // 設定ClassFilter
		setClassFilter(new TransactionAttributeSourceClassFilter());
	}

        // 方法是否與切點匹配
	@Override
	public boolean matches(Method method, Class<?> targetClass) {
                // 獲取TransactionAttributeSource,由上面的步驟可知返回的是AnnotationTransactionAttributeSource
		TransactionAttributeSource tas = getTransactionAttributeSource();
                 // 如果TransactionAttributeSource為空,或者從TransactionAttributeSource獲取到的事務屬性不為空都會返回true
		return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
	}
  
  // ClassFilter過濾器
  private class TransactionAttributeSourceClassFilter implements ClassFilter {

                // 切點是否與類匹配
		@Override
		public boolean matches(Class<?> clazz) {
                        // 如果TransactionalProxy、PlatformTransactionManager或者PersistenceExceptionTranslator的子類,則不匹配
			if (TransactionalProxy.class.isAssignableFrom(clazz) ||
					PlatformTransactionManager.class.isAssignableFrom(clazz) ||
					PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
				return false;
			}
                        // 獲取TransactionAttributeSource,由上文可知是AnnotationTransactionAttributeSource型別的
			TransactionAttributeSource tas = getTransactionAttributeSource();
                       // 呼叫isCandidateClass方法判斷是否是匹配
			return (tas == null || tas.isCandidateClass(clazz));
		}
	}

}

AnnotationTransactionAttributeSource

條件一:檢查類是否匹配事務切點

上面分析可知,檢查類是否與切點匹配時獲取了TransactionAttributeSource,呼叫它的isCandidateClass方法進行判斷,TransactionAttributeSource的具體實現是AnnotationTransactionAttributeSource:

  1. 在構造方法中,添加了註解解析器:
    • Spring事務註解解析器的實現類為SpringTransactionAnnotationParser,也是預設的註解解析器
    • 如果開啟了JTA或者EJB,將會分別新增對應的解析器。
  2. 實現了isCandidateClass方法,實際又是呼叫註解解析器的isCandidateClass判斷是否是候選類的。
@SuppressWarnings("serial")
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
		implements Serializable {

	private static final boolean jta12Present;

	private static final boolean ejb3Present;

	static {
		ClassLoader classLoader = AnnotationTransactionAttributeSource.class.getClassLoader();
		jta12Present = ClassUtils.isPresent("javax.transaction.Transactional", classLoader);
		ejb3Present = ClassUtils.isPresent("javax.ejb.TransactionAttribute", classLoader);
	}

	private final boolean publicMethodsOnly;
        // 註解解析器集合
	private final Set<TransactionAnnotationParser> annotationParsers;

	public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
		this.publicMethodsOnly = publicMethodsOnly;
                // 添加註解解析器
		if (jta12Present || ejb3Present) {
			this.annotationParsers = new LinkedHashSet<>(4);
                        // 新增Spring事務註解解析器
			this.annotationParsers.add(new SpringTransactionAnnotationParser());
			if (jta12Present) {
                                // JTA事務註解解析器
				this.annotationParsers.add(new JtaTransactionAnnotationParser());
			}
			if (ejb3Present) {
                                 // EJB3事務註解解析器
				this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
			}
		}
		else {
                         // 新增Spring事務註解解析器
			this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
		}
	}

        // 判斷是否是候選類
	@Override
	public boolean isCandidateClass(Class<?> targetClass) {
		for (TransactionAnnotationParser parser : this.annotationParsers) {
                        // 呼叫解析器的isCandidateClass方法判斷是否是候選類
			if (parser.isCandidateClass(targetClass)) {
				return true;
			}
		}
		return false;
	}

}

SpringTransactionAnnotationParser

  1. SpringTransactionAnnotationParser實現了isCandidateClass方法,它又呼叫了AnnotationUtils的isCandidateClass判斷目標類是否是Transactional註解的候選類,AnnotationUtils中isCandidateClass的具體判斷邏輯如下:

    • 如果註解類路徑以java.開頭,返回true,這裡Transactional註解不是java.開頭,它是Spring的註解類,所以這個條件不會成立

    • 如果目標類的類路徑以java.開頭,或者是Ordered型別,isCandidateClass返回false,說明目標類不是某個註解的候選類

    • 除去以上兩種情況之外,isCandidateClass都返回true

      總結: 如果目標類的類路徑不以java.開頭(也就是說它不是java的相關類),也不是Ordered型別,說明目標類是Transactional註解的候選類。

  2. SpringTransactionAnnotationParser實現了parseTransactionAnnotation方法,裡面包含對事物屬性的解析

public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {

	@Override
	public boolean isCandidateClass(Class<?> targetClass) {
                // 是否是Transactional註解的候選類
		return AnnotationUtils.isCandidateClass(targetClass, Transactional.class);
	}

        // 解析註解屬性
	@Override
	@Nullable
	public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
		AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
				element, Transactional.class, false, false);
		if (attributes != null) {
                        // 解析註解屬性
			return parseTransactionAnnotation(attributes);
		}
		else {
			return null;
		}
	}
    
       /**
        * 解析事務註解
        */
	public TransactionAttribute parseTransactionAnnotation(Transactional ann) {
		return parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, false, false));
	}

       /**
        * 解析事務註解
        */
	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;
	}

}

// AnnotationUtils
public abstract class AnnotationUtils {
     
        /**
	 * 檢查目標類clazz是否是註解的候選類
	 */
	public static boolean isCandidateClass(Class<?> clazz, Collection<Class<? extends Annotation>> annotationTypes) {
		for (Class<? extends Annotation> annotationType : annotationTypes) {
                        // 傳入目標類和註解,SpringTransactionAnnotationParser傳入的註解是Transactional
			if (isCandidateClass(clazz, annotationType)) {
				return true;
			}
		}
		return false;
	}
    
    /**
     * 檢查目標類clazz是否是註解的候選類
     */
    public static boolean isCandidateClass(Class<?> clazz, Class<? extends Annotation> annotationType) {
                // 傳入目標類和註解類路徑
		return isCandidateClass(clazz, annotationType.getName());
	}

	/**
	 * 檢查目標類clazz是否是註解的候選類
	 */
	public static boolean isCandidateClass(Class<?> clazz, String annotationName) {
                // 註解類路徑是否是java.開頭
		if (annotationName.startsWith("java.")) {
			return true;
		}
                // 呼叫AnnotationsScanner的hasPlainJavaAnnotationsOnly方法判斷
                // hasPlainJavaAnnotationsOnly方法的判斷邏輯是:如果目標類的類路徑以java.開頭或者是Ordered類會返回true
               // 所以如果目標類的類路徑以java.開頭或者是Ordered類,isCandidateClass會返回false,說明目標類不是註解的候選類
		if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
			return false;
		}
                // 如果註解類路徑不是java.開頭,並且目標類的類路徑不以java.開頭,也不是Ordered型別,返回true,說明目標類是某個註解的候選類
		return true;
	}
}

// AnnotationsScanner
abstract class AnnotationsScanner {
    static boolean hasPlainJavaAnnotationsOnly(Class<?> type) {
                // 如果目標類的類路徑以java.開頭或者是Ordered類
		return (type.getName().startsWith("java.") || type == Ordered.class);
	}
}

條件二:檢查方法是否匹配事務切點

AbstractFallbackTransactionAttributeSource

如果從TransactionAttributeSource獲取到的事務屬性不為空將會滿足切點的匹配條件,獲取事務屬性的方法實現在AbstractFallbackTransactionAttributeSource類中:

  1. 如果當前方法是Object中的方法,返回空
  2. 根據當前的方法和類的資訊構建快取key,從快取中獲取
    • 如果獲取不為空,判斷是否為空的事務屬性NULL_TRANSACTION_ATTRIBUTE,如果是則返回null,否則返回從快取中獲取到的事務屬性
    • 如果獲取為空,呼叫解析事務屬性的方法進行解析,然後放入快取中並返回
public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {
  
        // 空的TransactionAttribute
	@SuppressWarnings("serial")
	private static final TransactionAttribute NULL_TRANSACTION_ATTRIBUTE = new DefaultTransactionAttribute() {
		@Override
		public String toString() {
			return "null";
		}
	};
        // 快取
	private final Map<Object, TransactionAttribute> attributeCache = new ConcurrentHashMap<>(1024);

        // 獲取事務屬性
        @Override
	@Nullable
	public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
                // 如果當前方法所在的類是Object
		if (method.getDeclaringClass() == Object.class) {
			return null;
		}
		// 構建cacheKey
		Object cacheKey = getCacheKey(method, targetClass);
                // 首先根據cacheKey從快取中獲取
		TransactionAttribute cached = this.attributeCache.get(cacheKey);
		if (cached != null) {
			// 判斷是否為空的TRANSACTION_ATTRIBUTE
			if (cached == NULL_TRANSACTION_ATTRIBUTE) {
                                // 返回空
				return null;
			}
			else {
                                // 返回事務屬性TransactionAttribute
				return cached;
			}
		}
		else {
			// 解析TransactionAttribute
			TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
			// 如果為空,也加入快取,但是value是NULL_TRANSACTION_ATTRIBUTE
			if (txAttr == null) {
				this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
			}
			else {
				String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
                                // 如果是DefaultTransactionAttribute型別的
				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;
		}
	}

        // 獲取快取KEY
	protected Object getCacheKey(Method method, @Nullable Class<?> targetClass) {
		return new MethodClassKey(method, targetClass);
	}

	/**
	 * 解析TransactionAttribute
	 */
	@Nullable
	protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
		// 判斷方法是否是public的
		if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
			return null;
		}

		// 獲取目標方法
		Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

		// 在方法上查詢事務屬性的設定,findTransactionAttribute方法在AnnotationTransactionAttributeSource中實現
		TransactionAttribute txAttr = findTransactionAttribute方法(specificMethod);
		if (txAttr != null) {
			return txAttr;
		}

		// 在目標類上面查詢事務屬性的設定
		txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
		if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
			return txAttr;
		}

		if (specificMethod != method) {
			// 使用方法上配置的事務屬性
			txAttr = findTransactionAttribute(method);
			if (txAttr != null) {
				return txAttr;
			}
			// 使用類上面配置的事務屬性
			txAttr = findTransactionAttribute(method.getDeclaringClass());
			if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
				return txAttr;
			}
		}
		return null;
	}

}

總結

事務是基於AOP實現的,事務的Advisor是BeanFactoryTransactionAttributeSourceAdvisor,Advisor判斷方法是否匹配時,是通過Pointcut的matches方法判斷的,事務的Pointcut是TransactionAttributeSourcePointcut,裡面實現了方法是否與事務切點匹配的判斷:

  1. 對類的匹配是通過判斷目標類是否是Transactional註解的候選類實現的,我們建立的類一般不會以java.開頭,所以說可以與Transactional註解匹配成功。

  2. 對方法的匹配是通過解析方法上面配置的事務屬性判斷的,如果解析到了事務屬性,則滿足匹配條件。

TransactionInterceptor

TransactionInterceptor是事務Advisor的Advice,執行目標方法時,方法會被攔截,進入到TransactionInterceptor中,在TransactionInterceptor的invoke方法中實際是呼叫invokeWithinTransaction執行的:

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
  @Override
	@Nullable
	public Object invoke(MethodInvocation invocation) throws Throwable {
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

		// 通過事務執行目標方法,實現在TransactionAspectSupport方法中
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}
}

TransactionAspectSupport

TransactionAspectSupport中實現了invokeWithinTransaction方法:

  1. 獲取事務屬性TransactionAttribute和TransactionManager事務管理器
  2. 對響應式事務、宣告式事務和程式設計式事務分別進行判斷,以宣告式事務為例步驟如下:
    • 建立事務
    • 執行方法
    • 捕捉異常,如果丟擲異常進行回滾
    • 清除事務資訊
    • 提交事務
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
@Nullable
	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {

		// 獲取TransactionAttributeSource
		TransactionAttributeSource tas = getTransactionAttributeSource();
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
                // 獲取事務管理器TransactionManager
		final TransactionManager tm = determineTransactionManager(txAttr);
                // 響應式事務處理
		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);
		}

		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 {
				// This is an around advice: Invoke the next interceptor in the chain.
                                // 這是一個環繞通知,將會在攔截鏈中執行下一個攔截
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// 捕捉異常,進行回滾
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
                                // 清除事務
				cleanupTransactionInfo(txInfo);
			}

			if (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 {
			final ThrowableHolder throwableHolder = new ThrowableHolder();

			// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
			try {
				Object result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
                                        // 獲取事務資訊
					TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
					try {
                                                // 執行方法
						Object retVal = invocation.proceedWithInvocation();
						if (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);
					}
				});

				// Check result state: It might indicate a Throwable to rethrow.
				if (throwableHolder.throwable != null) {
					throw throwableHolder.throwable;
				}
				return result;
			}
			catch (ThrowableHolderException ex) {
				throw ex.getCause();
			}
			catch (TransactionSystemException ex2) {
				if (throwableHolder.throwable != null) {
					logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
					ex2.initApplicationException(throwableHolder.throwable);
				}
				throw ex2;
			}
			catch (Throwable ex2) {
				if (throwableHolder.throwable != null) {
					logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
				}
				throw ex2;
			}
		}
	}
}

總結

參考

【貓吻魚】Spring原始碼分析:全集整理

Spring版本:5.2.5.RELEASE