Spring事务学习总结


前言

Spring基于AOP完成的事务处理。接下来就是围绕着Spring是如何基于AOP完成的事务处理的学习总结

一、事务处理的核心类

提到AOP,就需要提到三个核心类Advisor、PointCut、Advice。Advisor主要用于封装后两者,PointCut用于匹配待增强的方法,Advice用于增强待增强的方法。以下就是事务中用到的核心类

类名所属类型简介
BeanFactoryTransactionAttributeSourceAdvisorAdvisor用于封装Advice和PointCut,便于Spring调用
AnnotationTransactionAttributeSourcePointCut该类本身不是PointCut的子类,spring使用适配器模式让其成为了一个PointCut
TransactionInterceptorAdvice用于增强需要事务处理的方法,事务处理的逻辑都在该类中

二、核心类的加载

Spring原始采用自定义标签的方式加载这三个类,在SpringBoot中使用了自动装配完成加载

2.1、自定义标签加载方式简介

大致过程如下

  • 1 这个标签加入spring的配置文件。
<tx:annotation-driven />
  • 2 TxNamespaceHandler类中的AnnotationDrivenBeanDefinitionParser类对自定义标签进行解析完成核心类加载
public BeanDefinition parse(Element element, ParserContext parserContext) {
		registerTransactionalEventListenerFactory(parserContext);
		String mode = element.getAttribute("mode");
		//目前不是aspectj模式 这里先不看了
		if ("aspectj".equals(mode)) {
			。。。
		}
		//重点看这里
		else {
			// mode="proxy"
			AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
		}
		return null;
	}

	//这里可以看到核心类的加载
	private static class AopAutoProxyConfigurer {

		public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
			AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

			String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
			if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
				Object eleSource = parserContext.extractSource(element);

				//构建AnnotationTransactionAttributeSource
				RootBeanDefinition sourceDef = new RootBeanDefinition(
						"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
				sourceDef.setSource(eleSource);
				sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
				String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

				//构建TransactionInterceptor
				RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
				interceptorDef.setSource(eleSource);
				interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
				registerTransactionManager(element, interceptorDef);
				interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
				String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

				//构建BeanFactoryTransactionAttributeSourceAdvisor
				RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
				advisorDef.setSource(eleSource);
				advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
				//向BeanFactoryTransactionAttributeSourceAdvisor注入AnnotationTransactionAttributeSource
				advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
				//向BeanFactoryTransactionAttributeSourceAdvisor注入TransactionInterceptor
				advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
				if (element.hasAttribute("order")) {
					advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
				}
				parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

				CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
				compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
				compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
				compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
				parserContext.registerComponent(compositeDef);
			}
		}
	}

以上就是自定义标签加载核心类的方式。

2.2、自动装配加载方式简介

大致过程如下

  • 1 默认自定装配列表【spring.factories】自带事务装配类TransactionAutoConfiguration
    在这里插入图片描述
  • 2 TransactionAutoConfiguration内部会开启@EnableTransactionManagement
@Configuration(proxyBeanMethods = false)
	@ConditionalOnBean(TransactionManager.class)
	@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
	public static class EnableTransactionManagementConfiguration {

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

		}

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

		}
	}
  • 3 @EnableTransactionManagement注解中带有TransactionManagementConfigurationSelector
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

}
  • 3 @TransactionManagementConfigurationSelector选择装配ProxyTransactionManagementConfiguration
@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
				//最终会进入这个分支
				return new String[] {AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {determineTransactionAspectClass()};
			default:
				return null;
		}
	}
  • 4 ProxyTransactionManagementConfiguration完成核心类装配
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
	//定义BeanFactoryTransactionAttributeSourceAdvisor
	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {

		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		//设置AnnotationTransactionAttributeSource
		advisor.setTransactionAttributeSource(transactionAttributeSource);
		//设置TransactionInterceptor
		advisor.setAdvice(transactionInterceptor);
		if (this.enableTx != null) {
			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		}
		return advisor;
	}
	
	//定义AnnotationTransactionAttributeSource
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		return new AnnotationTransactionAttributeSource();
	}

    //定义TransactionInterceptor 
	@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;
	}
}

三、结合AOP总结事务核心类的使用时机

这里总结的比较块,需要已经了解AOP的源码。以下基于AOP的源码来看看核心类【BeanFactoryTransactionAttributeSourceAdvisor、AnnotationTransactionAttributeSource、TransactionInterceptor】的使用时机。首先看看AOP的入口方法,该方法在AbstractAutoProxyCreator类中

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		...//获得与bean匹配的Advisor集合
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		//如果Advisor集合非空,开始构建代理对象
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

AOP的主流程就在这里。一共两步,

  • 其一获取所有与当前bean匹配的Advisor。结合事务来看主要是通过AnnotationTransactionAttributeSource于类进行匹配,如果匹配成功返回的Advisor集合就会包含BeanFactoryTransactionAttributeSourceAdvisor
  • 其二如果Advisor集合不为空,通过Advisor集合构建代理对象。结合事务来看最终会将BeanFactoryTransactionAttributeSourceAdvisor中的TransactionInterceptor封装到代理对象中完成事务控制
    接下来分别跟着下这两个分支

3.1 AnnotationTransactionAttributeSource的匹配时机和规则

protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
	//跟这个方法
	List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
	if (advisors.isEmpty()) {
		return DO_NOT_PROXY;
	}
	return advisors.toArray();
}

可以看到核心逻辑在findEligibleAdvisors方法中,继续跟进

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
	//获取所有Advisor
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
	//过滤出于bean匹配的Advisor
	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
	extendAdvisors(eligibleAdvisors);
	if (!eligibleAdvisors.isEmpty()) {
		eligibleAdvisors = sortAdvisors(eligibleAdvisors);
	}
	return eligibleAdvisors;
}

这里主要有两步

  • 获取所有的Advisor,这里包括BeanFactoryTransactionAttributeSourceAdvisor
  • 过滤出于bean匹配的Advisor

接着重点看过滤bean匹配的Advisor

protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
			//最终委托AopUtils来进行匹配
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}

将匹配工作委托给了AopUtils类,继续跟进findAdvisorsThatCanApply方法

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
	if (candidateAdvisors.isEmpty()) {
		return candidateAdvisors;
	}
	List<Advisor> eligibleAdvisors = new ArrayList<>();
	//BeanFactoryTransactionAttributeSourceAdvisor不是IntroductionAdvisor的子类 这个分支跳过
	for (Advisor candidate : candidateAdvisors) {
		if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
			eligibleAdvisors.add(candidate);
		}
	}
	boolean hasIntroductions = !eligibleAdvisors.isEmpty();
	for (Advisor candidate : candidateAdvisors) {
		if (candidate instanceof IntroductionAdvisor) {
			// already processed
			continue;
		}
		//匹配逻辑在这里
		if (canApply(candidate, clazz, hasIntroductions)) {
			eligibleAdvisors.add(candidate);
		}
	}
	return eligibleAdvisors;
}

我们关注的BeanFactoryTransactionAttributeSourceAdvisor不是IntroductionAdvisor的子类,所以IntroductionAdvisor相关的先跳过。重点看
canApply方法。

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		//进入这个分支 看起重载方法
		else if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
			//这里提取了Pointcut
			return canApply(pca.getPointcut(), targetClass, hasIntroductions);
		}
		else {
			// It doesn't have a pointcut so we assume it applies.
			return true;
		}
}

BeanFactoryTransactionAttributeSourceAdvisor是PointcutAdvisor的子类,所以可以强转。强制后可以拿到其内部的Pointcut。接着调用了
canApply的重载方法。

继续跟进之前,先了解下这里拿到的Pointcut是谁,和AnnotationTransactionAttributeSource有什么关系

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

	@Nullable
	private TransactionAttributeSource transactionAttributeSource;
	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
		@Override
		@Nullable
		protected TransactionAttributeSource getTransactionAttributeSource() {
			return transactionAttributeSource;
		}
	};


	/**
	 * Set the transaction attribute source which is used to find transaction
	 * attributes. This should usually be identical to the source reference
	 * set on the transaction interceptor itself.
	 * @see TransactionInterceptor#setTransactionAttributeSource
	 */
	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;
	}

}

这里可以看到Pointcut并不是TransactionAttributeSource,而是一个包含了TransactionAttributeSource的TransactionAttributeSourcePointcut。个人理解TransactionAttributeSourcePointcut相当于TransactionAttributeSource的一个适配器,用于支持spring的统一调用。其本质的匹配能力都是由TransactionAttributeSource来完成的。这里先做一个了解,等真正执行匹配时在进一步讨论。继续跟进canApply

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
		//这里的pc 目前就是TransactionAttributeSourcePointcut
		Assert.notNull(pc, "Pointcut must not be null");
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}
		
		//获取方法匹配器
		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}
		//这个分支不会进入 跳过
		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}
		
		//这里拿到bean的所有父类
		Set<Class<?>> classes = new LinkedHashSet<>();
		if (!Proxy.isProxyClass(targetClass)) {
			classes.add(ClassUtils.getUserClass(targetClass));
		}
		//将bean和其所有父类封装到classes集合
		classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
		//便利bean及其父类
		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;
				}
			}
		}
		return false;
	}

这个方法主要流程就是,从pc中获取方法匹配器MethodMatcher,然后通过MethodMatcher的matches方法和当前类全家的所有方法进行匹配。这里重点就是MethodMatcher是谁,还有其matches方法的逻辑。

TransactionAttributeSourcePointcut的getMethodMatcher方法是由其父类StaticMethodMatcherPointcut实现的。

public final MethodMatcher getMethodMatcher() {
	return this;
}

这里返回了this也就是说MethodMatcher本质上就是TransactionAttributeSourcePointcut,所以接下来看看TransactionAttributeSourcePointcut的matches方法

public boolean matches(Method method, Class<?> targetClass) {
		//这里拿到了TransactionAttributeSource 
		TransactionAttributeSource tas = getTransactionAttributeSource();
		//最终通过TransactionAttributeSource的getTransactionAttribute方法完成匹配
		return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

可以看到真正的匹配是由TransactionAttributeSource的getTransactionAttribute方法实现的,TransactionAttributeSourcePointcut本身只是一个适配器。那么设计之初为什么不把TransactionAttributeSource变成一个Pointcut,这里个人理解是TransactionAttributeSource本质是做@Transactional注解解析的和Pointcut没有一点关系,而Spring想通能否解析到@Transactional注解来做Pointcut的匹配结果,最终引入了TransactionAttributeSourcePointcut适配器继续跟getTransactionAttribute方法

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

		//缓存机制 这个分支先跳过
		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 {
			//最终通过txAttr是否为空来确定是否匹配
			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;
		}
	}

上边分析可以知道,是否匹配是根据txAttr 是否为空来判断的,所以需要看下computeTransactionAttribute方法

protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
		// Don't allow no-public methods as required.
		if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
			return null;
		}

		//获取原始方法,入参方法可能是接口方法。如果是接口方法这里会返回实现类方法
		Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

		//实现类方法中上的@Transactional 解析成TransactionAttribute  不为空直接返回
		TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
		if (txAttr != null) {
			return txAttr;
		}

		//实现类中上的@Transactional 解析成TransactionAttribute 不为空直接返回
		txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
		if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
			return txAttr;
		}
		//如果实现类方法和入参方法不一样 说明入参方法可能是个接口
		if (specificMethod != method) {
			//接口方法上的@Transactional 解析成TransactionAttribute 不为空直接返回
			txAttr = findTransactionAttribute(method);
			if (txAttr != null) {
				return txAttr;
			}
			//接口上的@Transactional 解析成TransactionAttribute 不为空直接返回
			txAttr = findTransactionAttribute(method.getDeclaringClass());
			if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
				return txAttr;
			}
		}

		return null;
	}

这里主要分了四步

  • 如果实现类方法上有@Transactional注解,将其解析成TransactionAttribute返回
  • 如果实现类上有@Transactional注解,将其解析成TransactionAttribute返回
  • 如果入参方法是接口方法,会继续向下走,否则返回null
  • 如果接口类方法上有@Transactional注解,将其解析成TransactionAttribute返回
  • 如果接口类上有@Transactional注解,将其解析成TransactionAttribute返回

为什么会提到@Transactional注解呢?需要接着看看findTransactionAttribute的实现

@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
	return determineTransactionAttribute(clazz);
}

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

这两个处理逻辑差不多,接下来随便选一个。就选入参是method的继续跟踪

//用于保存解析器
private final Set<TransactionAnnotationParser> annotationParsers;

//AnnotationTransactionAttributeSource无参构造器
public AnnotationTransactionAttributeSource() {
	this(true);
}

//AnnotationTransactionAttributeSource有参构造器
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
	this.publicMethodsOnly = publicMethodsOnly;
	if (jta12Present || ejb3Present) {
		this.annotationParsers = new LinkedHashSet<>(4);
		this.annotationParsers.add(new SpringTransactionAnnotationParser());
		if (jta12Present) {
			this.annotationParsers.add(new JtaTransactionAnnotationParser());
		}
		if (ejb3Present) {
			this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
		}
	}
	//会进入这个分支 解析器集合被初始化并添加SpringTransactionAnnotationParser解析器
	else {
		this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
	}
}
//接着跟进方法
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
	for (TransactionAnnotationParser parser : this.annotationParsers) {
		//通过上边分析 可以知道这里的parser就是SpringTransactionAnnotationParser
		TransactionAttribute attr = parser.parseTransactionAnnotation(element);
		if (attr != null) {
			return attr;
		}
	}
	return null;
}

这里除了determineTransactionAttribute方法,还把和determineTransactionAttribute方法相关的全局变量以及构造器也一起列出来了。AnnotationTransactionAttributeSource在构造时会初始化解析器集合annotationParsers,并添加SpringTransactionAnnotationParser解析器。最终determineTransactionAttribute方法会通过SpringTransactionAnnotationParser的parseTransactionAnnotation方法对元素进行解析

public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
	//寻找元素中的@Transactional注解,如果找到返回注解属性
	AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
			element, Transactional.class, false, false);
	if (attributes != null) {
		//将AnnotationAttributes解析成TransactionAttribute
		return parseTransactionAnnotation(attributes);
	}
	else {
		return null;
	}
}
//解析操作
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
		RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
	//这里的属性都是@Transactional中定义的,将其封装到TransactionAttribute中
	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;
}

这里可以看到其本质就是寻找元素上的@Transactional注解。并将@Transactional注解的属性解析后封装到TransactionAttribute对象中。

这里总结下AnnotationTransactionAttributeSource的匹配时机和规则
AnnotationTransactionAttributeSource的匹配时机是下寻找于bean匹配的Advisor时触发的,其匹配规则如下

  • 如果实现类方法上有@Transactional注解,将其解析成TransactionAttribute返回
  • 如果实现类上有@Transactional注解,将其解析成TransactionAttribute返回
  • 如果入参方法是接口方法,会继续向下走,否则返回null
  • 如果接口类方法上有@Transactional注解,将其解析成TransactionAttribute返回
  • 如果接口类上有@Transactional注解,将其解析成TransactionAttribute返回

最终只要返回的TransactionAttribute非空就算匹配成功,也可以理解为只要类中有@Transactional就会匹配成功

3.2 TransactionInterceptor的增强时机

接着跟下代理类的创建逻辑

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.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
		//拿到Advisor集合 这里包括BeanFactoryTransactionAttributeSourceAdvisor
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}
		//创建代理类 跟这里
		return proxyFactory.getProxy(getProxyClassLoader());
	}

这里主要是将Advisor集合传给ProxyFactory,然后委托ProxyFactory 完成代理类创建,继续跟getProxy

public Object getProxy(@Nullable ClassLoader classLoader) {
	return createAopProxy().getProxy(classLoader);
}

这里主要两步,第一通过createAopProxy获取是cglib代理工厂还是jdk代理工厂,第二通过getProxy方法构建代理对象。jdk比较熟悉这里假设返回的是jdk的代理工厂JdkDynamicAopProxy。接着跟下JdkDynamicAopProxy的getProxy方法

public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
	}
	Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
	findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
	//动态代理构建代理对象
	return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

这里可以看到动态代理了。最后一个处理器的参数传入this,也就是说JdkDynamicAopProxy本质就是InvocationHandler,所以其一定有invoke方法。继续跟中

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	Object oldProxy = null;
	boolean setProxyContext = false;

	TargetSource targetSource = this.advised.targetSource;
	Object target = null;

	try {
		...Object retVal;

		if (this.advised.exposeProxy) {
			// Make invocation available if necessary.
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}

		// Get as late as possible to minimize the time we "own" the target,
		// in case it comes from a pool.
		target = targetSource.getTarget();
		Class<?> targetClass = (target != null ? target.getClass() : null);

		//这里获得了一个增强方法链
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

		//如果无增强方法,直接调用连接点方法
		if (chain.isEmpty()) {
			// We can skip creating a MethodInvocation: just invoke the target directly
			// Note that the final invoker must be an InvokerInterceptor so we know it does
			// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
		}
		else {
			// We need to create a method invocation...
			MethodInvocation invocation =
					new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
			//增强方法的调用 跟这里
			retVal = invocation.proceed();
		}

		// Massage return value if necessary.
		Class<?> returnType = method.getReturnType();
		if (retVal != null && retVal == target &&
				returnType != Object.class && returnType.isInstance(proxy) &&
				!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
			// Special case: it returned "this" and the return type of the method
			// is type-compatible. Note that we can't help if the target sets
			// a reference to itself in another returned object.
			retVal = proxy;
		}
		else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
			throw new AopInvocationException(
					"Null return value from advice does not match primitive return type for: " + method);
		}
		return retVal;
	}
	finally {
		if (target != null && !targetSource.isStatic()) {
			// Must have come from TargetSource.
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			// Restore old proxy.
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}

该方法比较长,不展开一一描述了,其主要流程如下

  • getInterceptorsAndDynamicInterceptionAdvice方法通过Advisor集合获取MethodInterceptor集合。这里目的有三个
    • 其一是Advisor集合是整个类的增强方法,所以需要二次过滤获取针对当前方法的增强方法集合
    • 其二是提取Advisor中的Advice,因为增强方法只要Advice就够用了。其中BeanFactoryTransactionAttributeSourceAdvisor 中拿到的advice就是TransactionInterceptor
    • 其三是个别Advice不是MethodInterceptor的子类需要做适配。统一适配成MethodInterceptor的目的是为了保证增强方法的执行顺序TransactionInterceptor就是MethodInterceptor的子类所以无需适配
  • 将MethodInterceptor集合封装到ReflectiveMethodInvocation并执行其proceed方法进行增强方法的调用。继续跟proceed
public Object proceed() throws Throwable {
		//this.interceptorsAndDynamicMethodMatchers 这里就是MethodInterceptor集合
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}

		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		//有方法重载的会走整个分支
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			// Evaluate dynamic method matcher here: static part will already have
			// been evaluated and found to match.
			InterceptorAndDynamicMethodMatcher dm =
					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
			Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
			
			if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
				return dm.interceptor.invoke(this);
			}
			else {
				// Dynamic matching failed.
				// Skip this interceptor and invoke the next in the chain.
				return proceed();
			}
		}
		//一般会进入这个分支 即执行MethodInterceptor的invoke方法
		else {
			// It's an interceptor, so we just invoke it: The pointcut will have
			// been evaluated statically before this object was constructed.
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

到这里可以知道TransactionInterceptor的invoke方法会被执行。接着跟踪invoke

public Object invoke(MethodInvocation invocation) throws Throwable {
		
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

		//事务增强的全部逻辑都在该方法中执行
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}

TransactionInterceptor的增强逻辑都是在invokeWithinTransaction中实现的。该方法非常复杂涉及到了对事务传播性的处理。需要花费大量篇幅总结所以单独提取了一个分支TransactionInterceptor声明式学习总结


总结

Spring对事务的处理是基于AOP实现的,主要使用了三个核心类【BeanFactoryTransactionAttributeSourceAdvisor、AnnotationTransactionAttributeSource、TransactionInterceptor】。总结了核心类的加载、并且结合AOP的源码总结了核心类的调用时机。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值