Spring事务管理源码深度解读(一)

本文深入探讨了Spring如何通过@Transactional实现声明式事务管理,重点分析了@EnableTransactionManagement注解、TransactionManagementConfigurationSelector、AutoProxyRegistrar和ProxyTransactionManagementConfiguration的作用。文章详细解释了proxyTargetClass参数对代理模式的影响,以及mode参数对切面方式的选择。内容涵盖TransactionAttributeSource、TransactionInterceptor和BeanFactoryTransactionAttributeSourceAdvisor等核心组件,并预告下篇将深入解析事务管理的核心代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

熟悉spring的人大都熟悉@Transactional这个事务注解及其功能,这里就不详述了,但是spring是如何通过@Transactional实现声明式事物的呢?本文主要通过追踪spring相关源码来详细阐述实现过程,以达到知其然并知其所以然的效果。

@EnableTransactionManagement

那就先来看看@EnableTransactionManagement这个spring注解,顾名思义这个注解的功能就是打开spring的声明式事物的功能。来看看@EnableTransactionManagement的源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
   
   

	/**
	 * Indicate whether subclass-based (CGLIB) proxies are to be created ({@code true}) as
	 * opposed to standard Java interface-based proxies ({@code false}). The default is
	 * {@code false}. <strong>Applicable only if {@link #mode()} is set to
	 * {@link AdviceMode#PROXY}</strong>.
	 * <p>Note that setting this attribute to {@code true} will affect <em>all</em>
	 * Spring-managed beans requiring proxying, not just those marked with
	 * {@code @Transactional}. For example, other beans marked with Spring's
	 * {@code @Async} annotation will be upgraded to subclass proxying at the same
	 * time. This approach has no negative impact in practice unless one is explicitly
	 * expecting one type of proxy vs another, e.g. in tests.
	 */
	boolean proxyTargetClass() default false;

	/**
	 * Indicate how transactional advice should be applied.
	 * <p><b>The default is {@link AdviceMode#PROXY}.</b>
	 * Please note that proxy mode allows for interception of calls through the proxy
	 * only. Local calls within the same class cannot get intercepted that way; an
	 * {@link Transactional} annotation on such a method within a local call will be
	 * ignored since Spring's interceptor does not even kick in for such a runtime
	 * scenario. For a more advanced mode of interception, consider switching this to
	 * {@link AdviceMode#ASPECTJ}.
	 */
	AdviceMode mode() default AdviceMode.PROXY;

	/**
	 * Indicate the ordering of the execution of the transaction advisor
	 * when multiple advices are applied at a specific joinpoint.
	 * <p>The default is {@link Ordered#LOWEST_PRECEDENCE}.
	 */
	int order() default Ordered.LOWEST_PRECEDENCE;
}
  • proxyTargetClass
    配置参数proxyTargetClass默认为false就是使用jdk接口代理(java.lang.reflect.Proxy)模式(目标代理类必须实现接口才能生效),设置为true时就是使用CGLIB代理模式(当目标代理类未实现接口时可以使用), **注意:**这个参数的生效的条件 是mode=AdviceMode.PROXY,也就是切面方式使用的是spring aop而不是aspectj, 至于spring aop和aspectj的区别可以看看这篇文章 Comparing Spring AOP and AspectJ
  • mode
    切面方式默认为spring aop 只适用于spring容器管理的bean
  • order
    这个order参数在当同一个joinpoint有多个切面动作(advice)时,可以决定多个advice执行的先后顺序

这里主要来分析spring aop 官方文档aop-proxying 模式下的声明式事务的实现。

1. TransactionManagementConfigurationSelector

可以看到@EnableTransactionManagement 引入了TransactionManagementConfigurationSelector这个事物管理器配置选择器的类定义,进去看看这个类源码

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: //默认使用spring aop的代理模式
				return new String[] {
   
   AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case 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);
	}

}

因为我们现在分析默认模式下的spring aop代理模式,因此selectImports方法引入的类声明定义有AutoProxyRegistrar和ProxyTransactionManagementConfiguration这两个。

2. AutoProxyRegistrar
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
   
   
	private final Log logger = LogFactory.getLog(getClass());
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
   
   
		boolean candidateFound = false;
		Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
		for (String annoType : annoTypes) {
   
   
			AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
			if (candidate == null) {
   
   
				continue;
			}
			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) {
   
   
					//若是spring aop 模式则注册一些spring内置的自动代理生成器
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					if ((Boolean) proxyTargetClass) {
   
   
						//设置cglib代理模式
						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.registerAutoProxyCreatorIfNecessary(registry)
    若是spring aop的模式 则会自动注册一些spring内置的AutoProxyCreator自动代理生成器,来看看源码
public abstract class AopConfigUtils {
   
   

	/**
	 * The bean name of the internally managed auto-proxy creator.
	 */
	public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
			"org.springframework.aop.config.internalAutoProxyCreator";

	/**
	 * Stores the auto proxy creator classes in escalation order.
	 */
	private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);

	static {
   
   
		// Set up the escalation list...
		APC_PRIORITY_LIST
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值