聊一聊Spring中的@Transactional注解【上】【源码详解】

时间:2024-11-05 07:12:57

一、事务管理核心类及注解

1.1事务管理启动注解

/**
 * 启用Spring注解驱动的事务管理功能,类似XML配置中的<tx:*>
 * 应用在@Configuration注解的配置类上
 * 配置传统的,命令式事务管理或者响应式事务管理
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

	/**
	 * true:CGLIB
	 * false:JDK动态代理
	 * 注意两点:
	 * 1、该设置只会影响需要代理的类以何种方式被代理,但是不能完全决定。
	 * 2、这是一个全局的设置,将会影响所有spring管理需要被代理的bean。
	 */
	boolean proxyTargetClass() default false;

	/**
	 * 表名事务通知应该怎么被应用。
	 * 默认值是AdviceMode.PROXY
	 * 代理模式只允许通过代理拦截调用
	 * 同一个类中的局部调用不会被拦截
	 * 本地调用中方法上的@Transactional注解将被忽略,因为Spring的拦截器不会在此类运行时场景中发挥作用
	 * 需要更高级的拦截模式,使用AdviceMode.ASPECTJ
	 */
	AdviceMode mode() default AdviceMode.PROXY;

	/**
	 * 同一个连接点上多个通知时,事务advisor的执行顺序
	 */
	int order() default Ordered.LOWEST_PRECEDENCE;

}

1.2事务管理配置选择器

/**
 * 根据@EnableTransactionManagement中的模式,选择AbstractTransactionManagementConfiguration的实现。
 */
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

	/**
	 * PROXY:ProxyTransactionManagementConfiguration
	 * ASPECTJ:AspectJ(Jta)TransactionManagementConfiguration
	 */
	@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;
		}
	}

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

}

1.3自动代理创建器

/**
 * 基于@EnableTransactionManagement中的proxyTargetClass和adviceMode配置
 * 在BeanDefinitionRegistry上注册一个自动代理创建器
 */
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");
			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(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));
		}
	}

}

1.4代理事务管理配置

/**
 * 这个配置类配置了spring的一些基础设施bean,这些bean都是基于代理和注解驱动事务管理所需要的。
 */
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
	// advisor
	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {

		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		advisor.setTransactionAttributeSource(transactionAttributeSource);
		advisor.setAdvice(transactionInterceptor);
		if (this.enableTx != null) {
			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		}
		return advisor;
	}
	
    // 注解事务属性源
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		return new AnnotationTransactionAttributeSource();
	}
	
    // advice
	@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;
	}

}

1.5@Transactional

/**
 * 在独立的方法或者类上描述一个事务属性。
 *  
 * 注解在类上,应用在该类及子类所有方法上。
 * 不会向上应用到父类上;
 * 继承的方法需要重新声明,才能参与到子类级别的注解应用中。
 *
 *
 * 如果在此注解中没有配置自定义回滚规则,则事务将对RuntimeException和Error进行回滚,但不会对已检异常进行回滚。
 *
 * 回滚规则决定在抛出给定异常时是否应该回滚事务,这些规则是基于模式的。模式可以是一个完全限定类名,
 * 也可以是一个异常类型的完全限定类名的子字符串(必须是Throwable的子类),目前不支持通配符。
 *
 * 回滚规则可以通过rollbackFor、noRollbackFor、rollbackForClassName、noRollbackForClassName配置,
 * 它们允许将模式分别指定为Class引用或String。
 *
 * 有关此注解中其他属性语义的具体信息,参考:
 * org.springframework.transaction.TransactionDefinition
 * org.springframework.transaction.interceptor.TransactionAttribute
 *
 * 事务管理
 *
 * 该注解通常与由PlatformTransactionManager管理的线程绑定事务一起工作,将事务暴露给当前执行线程内的所有数据访问操作。
 * 注意:这不会传播到方法内新启动的线程
 *
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {

	@AliasFor("transactionManager")
	String value() default "";

	@AliasFor("value")
	String transactionManager() default "";

	String[] label() default {};

	/**
	 * 事务传播类型。
	 * 默认是PROPAGATION_REQUIRED
	 */
	Propagation propagation() default Propagation.REQUIRED;

	/**
	 * 事务隔离级别
	 * 默认值是Isolation.DEFAULT
	 */
	Isolation isolation() default Isolation.DEFAULT;

	/**
	 * 事务超时时间
	 */
	int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

	String timeoutString() default "";

	/**
	 * 只读标志
	 */
	boolean readOnly() default false;

	/**
	 * 定义0个或多个异常,它们必须是Throwable的子类,表示哪些异常类型必须导致事务回滚。
	 */
	Class<? extends Throwable>[] rollbackFor() default {};

	String[] rollbackForClassName() default {};

	/**
	 * 定义0个或多个异常,它们必须是hrowable的子类,表示哪些异常类型不进行事务回滚。
	 */
	Class<? extends Throwable>[] noRollbackFor() default {};

	String[] noRollbackForClassName() default {};

}

二、bean注册

2.1配置类事务相关注解解析

  • 实例化ConfigurationClassPostProcessor
  • 在容器中找到AppConfig这个配置类(@Configuration)
  • 解析配置类上的注解
  • 解析@Import注解时发现TransactionManagementConfigurationSelector
    1. 通过选择器找到AutoProxyRegistrar和ProxyTransactionManagementConfiguration
    2. 将AutoProxyRegistrar添加到AppConfig的importBeanDefinitionRegistrars中
    3. ProxyTransactionManagementConfiguration作为配置类继续解析
    4. 自身构建为beanDefinition,将@Bean注解的三个bean解析出来,外加一个父类的@Bean
  • 加载注册所有解析出来的bean定义信息(this.reader.loadBeanDefinitions(configClasses))
  • loadBeanDefinitionsFromRegistrars通过AutoProxyRegistrar将internalAutoProxyCreator注册到容器

2.2bean注册结果

invokeBeanFactoryPostProcessors(beanFactory)新增11个bean定义信息:

image-20241031140409280

  • jdbcTemplatetransactionManagerdataSource由主配置类Appconfig中的@Bean解析而来。
  • userServiceuserDaoImpl由组件扫描而来。
  • @EnableTransactionManagement中@Import引入的TransactionManagementConfigurationSelector选择器返回了配置类ProxyTransactionManagementConfiguration和注册器AutoProxyRegistrar。
  • AutoProxyRegistrar注册器注册了internalAutoProxyCreator
  • internalTransactionalEventListenerFactory是ProxyTransactionManagementConfiguration继承了AbstractTransactionManagementConfiguration,AbstractTransactionManagementConfiguration中的@Bean解析而来。
  • internalTransactionAdvisortransactionAttributeSourcetransactionInterceptor是配置类ProxyTransactionManagementConfiguration中@Bean解析而来。

三、bean实例化

3.1实例化结果

registerBeanPostProcessors(beanFactory)后新增3个单例:

image-20241031142944407

四、代理创建

4.1创建时机

  • 单例(如:UserService)构建过程中,初始化bean时(initializeBean),BeanPostProcessor(InfrastructureAdvisorAutoProxyCreator)会被应用
// AbstractAutoProxyCreator
// InfrastructureAdvisorAutoProxyCreator继承AbstractAutoProxyCreator,实现BeanPostProcessor
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

InfrastructureAdvisorAutoProxyCreator

4.2创建过程

  • 查找所有的Advisor(当前容器中只有一个BeanFactoryTransactionAttributeSourceAdvisor)
  • 查找符合条件的Advisor(目标类中有方法有@Transactional注解)
    1. 遍历目标类的所有方法
      • 读取方法上@Transactional所有属性
      • 解析所有属性,构建RuleBasedTransactionAttribute
  • 代理工厂创建(ProxyFactory)
  • 创建CGLIB AOP代理(ObjenesisCglibAopProxy)
  • 获取callbacks(第一个还是DynamicAdvisedInterceptor[advised中的advisors中只有BeanFactoryTransactionAttributeSourceAdvisor])
  • 创建代理类并实例化
  • callbacks赋值(((Factory) proxyInstance).setCallbacks(callbacks))
  • 创建完成

4.3代理对象创建核心源码

// AbstractAutoProxyCreator
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {

    // 查找能应用到bean上的Advice和Advisor
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    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;
}
// AbstractAdvisorAutoProxyCreator
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 查找候选Advisor
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 查找符合条件的Advisor
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
    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;
    }

    Set<Class<?>> classes = new LinkedHashSet<>();
    if (!Proxy.isProxyClass(targetClass)) {
        classes.add(ClassUtils.getUserClass(targetClass));
    }
    classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
	
    for (Class<?> clazz : classes) {
        Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
        // 遍历方法
        for (Method method : methods) {
            if (introductionAwareMethodMatcher != null ?
                    introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                	// methodMatcher是TransactionAttributeSourcePointcut
                    methodMatcher.matches(method, targetClass)) {
                return true;
            }
        }
    }

    return false;
}
// TransactionAttrobuteSourcePointcut
public boolean matches(Method method, Class<?> targetClass) {
    TransactionAttributeSource tas = getTransactionAttributeSource();
    // getTransactionAttribute如果不为空说明该方法上有@Transactional,且属性值已经被解析好构建了规则对象
    return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
// CglibAopProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
		}

		try {
			// 省略部分代码...

			// 创建配置CGLIB Enhancer...
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if (classLoader instanceof SmartClassLoader &&
						((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
					enhancer.setUseCache(false);
				}
			}
			enhancer.setSuperclass(proxySuperClass);
			enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
			
            // 0号位 DynamicAdvisedInterceptor(BeanFactoryTransactionAttributeSourceAdvisor)
			Callback[] callbacks = getCallbacks(rootClass);
			Class<?>[] types = new Class<?>[callbacks.length];
			for (int x = 0; x < types.length; x++) {
				types[x] = callbacks[x].getClass();
			}
			enhancer.setCallbackFilter(new