Spring Boot 事务实现原理(一)

1.事务相关的类

spring 事务也是通过 aop 实现的,那肯定也有切面、切点、通知、为目标对象创建代理对象,代理对象执行目标方法等等。

先小小回顾一下普通 aop 的相关知识点:

  • 切面、切点、通知 都是自定义的,根据需求开发不同的切面。
  • 在项目启动时,AnnotationAwareAspectJAutoProxyCreator 解析了所有切面 ,为每一个通知创建一个增强器,并将所有的增强器注入容器中。
  • 在项目启动时, bean被创建后要执行初始化,在初始化过程中,AnnotationAwareAspectJAutoProxyCreator 发现该 bean 被增强器命中了(切了),就为该 bean 创建代理对象,并将代理对象注入容器中。
  • 最后是代理对象执行目标方法,并在恰当的时候执行通知。

事务肯定也有对应的组件以及流程。

但与普通 aop 不同的是,事务的通知内容不是千变万化的,它是固定的,而且 spring 已经已经写好了,我们只需要拿来使用就可以了。通知被解析后会变成一个增强器,既然通知的内容都固定了且已知了,那是不是增强器的主要内容也已经是固定的,后续只需要将切面以及其他少部分信息 set 进增强器就行了,所以事务的增强器 spring 也已经帮我们写好了,我们也只需要拿来使用就可以了。

So:

  • TransactionInterceptor 这就是事务的通知 Advice。
  • BeanFactoryTransactionAttributeSourceAdvisor 事务的增强器。
  • TransactionAttributeSourcePointcut : 切点。主要负责方法匹配,就是找方法上有没有注解 @Transactional
  • TransactionAttributeSource:解析方法上的 @Transaction 注解中属性。并且将解析结果缓存到 map 中。
  • InfrastructureAdvisorAutoProxyCreator : 这是个 beanBostProcessor,为增强器命中的目标对象创建代理对象。

貌似缺了一个切面类,不缺的,因为事务的解析过程和普通 aop 不一样:

  • 普通aop 解析过程,先从容器中拿所有 Object.class,看类脑门上有没有 @Aspect 注解,再解析切面的通知,为通知创建增强器. bulabulabula…。
  • 事务解析过程,直接从容器中拿 Advisor.class,它是直接拿增强器。

2. 事务准备过程

也可以说叫配置过程,事务需要用到上面 6 个类,怎么把这些类配置到项目中去呢?只有配置妥当了,启动时才能加载到,最后才能发挥事务的威力。

很简单,只需在配置类上加 @EnableTransactionManagement 注解。意为”启动事务管理“。

看下这个注解做了什么。

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

@Import(TransactionManagementConfigurationSelector.class) 会在项目启动执行 BeanFactoryPostProcessor 时将 TransactionManagementConfigurationSelector 注入容器。

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:
                return new String[] {determineTransactionAspectClass()};
            default:
                return null;
        }
    }
	// 剩余代码不贴了。
}

selectImports(AdviceMode adviceMode) 返回了一组全限定类名,在项目启动过程中,会根据类名解析每一个类。这里会解析两个类:AutoProxyRegistrar.classProxyTransactionManagementConfiguration.class

解析这两个类,到底是做了什么事情?

ProxyTransactionManagementConfiguration 有 Configuration 注解,那它就是个配置类,类中方法上有 @Bean 注解,这就很明了了。解析这个类实际上是向容器中注入了 bean。

注入了谁的bean?

@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();
        // 往增强器中set transactionAttributeSource,
        // transactionAttributeSource 会解析方法上的 @Transactional 注解,将结果保存到增强器中。
        advisor.setTransactionAttributeSource(transactionAttributeSource);
        // 往增强器中set 通知。
        advisor.setAdvice(transactionInterceptor);
        if (this.enableTx != null) {
            advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
        }
        return advisor;
    }

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

}

AutoProxyRegistrarInfrastructureAdvisorAutoProxyCreator 注入到了容器。

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));
		}
	}

}

往下走…

@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAutoProxyCreatorIfNecessary(registry, null);
}
// ----
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
    BeanDefinitionRegistry registry, @Nullable Object source) {
	// 关键信息:InfrastructureAdvisorAutoProxyCreator.class
    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;
    }
	// cls = InfrastructureAdvisorAutoProxyCreator.class
    // 为 cls 创建 beanDefinition。
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    // 将 beanDefinition 注入容器。
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

就这么一个注解,将:

  • 事务通知: TransactionInterceptor

  • 事务的增强器:BeanFactoryTransactionAttributeSourceAdvisor

  • 解析Transaction注解 :TransactionAttributeSource

  • 为增强器命中的目标对象创建代理对象:InfrastructureAdvisorAutoProxyCreator

全都给配置好了,在项目启动过程中,这些类都会被注入容器。

准备过程结束后,开始下面的阶段:1. 将目标对象变成代理对象,2. 代理对象执行目标方法。

3. 将目标对象变成代理对象

这个阶段和普通 aop 几乎是一样的:先是生成 bean,在bean 的初始化阶段,如果 bean 被切了,就为bean生成代理对象。bean 的注入过程这里就不再描述了,这是 IOC 的过程。

直接场景假设:UserService 的 bean 已经被 create 完毕,接下来执行 initializeBean() 方法是为其创建代理对象。

@Service
public class UserService {
    @AutoWired
    public UserRepository userRepository;
    
    @Transactional
	public void testTranscation() throws Exception {
		userRepository.updateUserMoney("diego",900);
	}
}

这个过程要做三件事情:

  1. 从容器中获取增强器,是通过解析切面的方式,还是直接拿增强器,增强器都会被拿到。
  2. 判断 bean 是否被增强器切了。
  3. 如果被增强器切了,为 bean 生成代理对象。

3.1 从容器中获取事务的增强器

和普通 aop 的过程一样,事务的增强器也是在 create bean 之前就解析并注入容器了,在 bean 的初始化阶段直接从容器中拿增强器(如果没拿到才会再次解析,但一般都是拿到了)。

// AbstractAutowireCapableBeanFactory.java
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
               // 走这里.....
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}

// ---
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // AnnotationAwareAspectJAutoProxyCreator 调用 postProcessBeforeInstantiation()方法。
            Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
            if (result != null) {
                return result;
            }
        }
    }
    return null;
}

进去看看

// AbstractAutoProxyCreator.java
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    Object cacheKey = getCacheKey(beanClass, beanName);

    if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
        if (this.advisedBeans.containsKey(cacheKey)) {
            return null;
        }
        // 在 shouldSkip 方法里解析的增强器并且缓存起来。
        if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return null;
        }
    }
// AspectJAwareAdvisorAutoProxyCreator.java
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    // 获取项目中所有的增强器。
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    for (Advisor advisor : candidateAdvisors) {
        if (advisor instanceof AspectJPointcutAdvisor &&
            ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
            return true;
        }
    }
    return super.shouldSkip(beanClass, beanName);
}
// ----
protected List<Advisor> findCandidateAdvisors() {
    // 先获取事务的增强器。
    List<Advisor> advisors = super.findCandidateAdvisors();
    if (this.aspectJAdvisorsBuilder != null) {
        // 接下来再解析用户自定义的切面,生成增强器。
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    // 返回找到的所有的增强器。
    return advisors;
}

最后一步了,看看怎么获取的事务的增强器。

// AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> findCandidateAdvisors() {
    Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
    return this.advisorRetrievalHelper.findAdvisorBeans();
}
// BeanFactoryAdvisorRetrievalHelper.java
public List<Advisor> findAdvisorBeans() {
    // 先看下增强器之前有没有被获取到,如果有就直接去缓存中拿,不过没有再创建。
    String[] advisorNames = this.cachedAdvisorBeanNames;
    // 第一次肯定是之前没有被获取过,后续再次获取就是去缓存中直接拿了。
    if (advisorNames == null) {

        // 从 beanFactory 中获取所有的 Advisor.class 类型的 beanName。它的 beanDefinition 存在或者直接是 bean 都可以。
        // 因为事务的通知spring已经写好了,直接通过增强器给注进来了,做以直接通过 Advisor.class 类型拿就行了。
        // 不需要再走普通 aop 那套,先找切面,再找通知,最后为通知 new Advisor()。
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
            this.beanFactory, Advisor.class, true, false);
        // 将拿到的 advisorNames 保存到 cachedAdvisorBeanNames 中,表示这些 name 的增强器已经被缓存了。
        this.cachedAdvisorBeanNames = advisorNames;
    }
    if (advisorNames.length == 0) {
        return new ArrayList<>();
    }

    // 保存所有的 advisor bean。
    List<Advisor> advisors = new ArrayList<>();
    // 遍历 advisorNames 获取每一个 advisor。
    // 如果 bean存在直接从单例池中拿,
    // 如果bean 不存在,通过 beanDefinition 创建一个。
    for (String name : advisorNames) {
        // 名字是合法的。
        if (isEligibleBean(name)) {
            // 如果正在创建中,那啥也不干,就打个日志。
            if (this.beanFactory.isCurrentlyInCreation(name)) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Skipping currently created advisor '" + name + "'");
                }
            }
            else {
                // 如果不处于正在创建中,那么 getBean() 将其获取。单例池中有,直接拿,没有,走 createBean() 创建一个。
                try {
                    // (先获取),再将拿到的 advisor 缓存到 advisors 中。
                    advisors.add(this.beanFactory.getBean(name, Advisor.class));
                }
                catch (BeanCreationException ex) {
                    Throwable rootCause = ex.getMostSpecificCause();
                    if (rootCause instanceof BeanCurrentlyInCreationException) {
                        BeanCreationException bce = (BeanCreationException) rootCause;
                        String bceBeanName = bce.getBeanName();
                        if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
                            if (logger.isTraceEnabled()) {
                                logger.trace("Skipping advisor '" + name +
                                             "' with dependency on currently created bean: " + ex.getMessage());
                            }
                            // Ignore: indicates a reference back to the bean we're trying to advise.
                            // We want to find advisors other than the currently created bean itself.
                            continue;
                        }
                    }
                    throw ex;
                }
            }
        }
    }
    // 返回拿到的所有 Advisor。
    return advisors;
}

从这里可以看到,所谓的获取增强器,一方面是真的拿到增请器并返回给函数调用,另一方面是指增强器被注入到了容器中。

在后面的初始化 bean 中,直接从容器中拿增强器。

3.2 判断 bean 是否被增强器切了

判断逻辑也很简单,UserService 的 Class 对象,依次去下面四个地方找有没有 @Transaction 注解,只要有一个地方有那就是被切了。

  1. UserService 的 每 public 一个方法上。
  2. UserService 类上。
  3. UserService 父类接口的每一个方法上。
  4. UserService 父类接口上。

下面看下具体的代码实现:

// AbstractAutoProxyCreator.java

/**
	这里面:
	1. 获取所有的增强器。
	2. 删选有没有增强器切bean。
	3. 如果有,为 bean 创建代理对象。
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // 项目中的所有增强器在 doCreateBean 之前就已经解析好了,
    // 这里是:1. 从容器中获取所有增强器;2. 筛选出那些切了当前 bean 的增强器,并返回。
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    //  如果 specificInterceptors 不为空,说明 bean 被切了。
    if (specificInterceptors != DO_NOT_PROXY) {
        // 设置需要为 cacheKey 创建代理。(标识符而已)
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 创建代理。
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        // 保存 cacheKey 的代理。
        this.proxyTypes.put(cacheKey, proxy.getClass());
        // 返回创建好的代理对象。
        return proxy;
    }
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

整体逻辑都在这里了,再往下走看下 判断 bean 被切的具体细节。

// AbstractAutoProxyCreator.java
protected Object[] getAdvicesAndAdvisorsForBean(
    Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
    // 为 beanClass 寻找符合条件的增强器(advisors)
    List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY;
    }
    return advisors.toArray();
}
// ---
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    // 找到所有候选的 advisors,包括事务的 advisor 和 普通 aop 的 advisor。。
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 在所有的 advisors 中筛选出切 bean 的 advisor。
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    //  返回符合条件的 advisor
    return eligibleAdvisors;
}
// ---
protected List<Advisor> findAdvisorsThatCanApply(
    List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

    ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    try {
        // 走这里....
        return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    }
    finally {
        ProxyCreationContext.setCurrentProxiedBeanName(null);
    }
}

进到 AopUtils.java 中再看看

// AopUtils.java
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {if (candidateAdvisors.isEmpty()) {
        return candidateAdvisors;
    }
    List<Advisor> eligibleAdvisors = new ArrayList<>();
    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) {
            continue;
        }
        //  在判断 advisor 能否使用在 clazz 上。
        if (canApply(candidate, clazz, hasIntroductions)) {
            // 如果可以,保存。
            eligibleAdvisors.add(candidate);
        }
    }
    // 返回所有能使用在 clazz 上的的 advisor。
    return eligibleAdvisors;
}
// ---
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;
        // 走这里.....。
        return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    }
    else {
        return true;
    }
}
// ---
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));
	
    // classes 中只有 UserService 的类对象。
    for (Class<?> clazz : classes) {
        // 获取类中的全部方法。
        Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
        // 遍历每一个方法。(看方法上是否有 @Transaction 注解或者类上有 @Transaction 注解)
        for (Method method : methods) {
            if (introductionAwareMethodMatcher != null ?
                introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                // 在这里判断的。
                methodMatcher.matches(method, targetClass)) {
                return true;
            }
        }
    }

    return false;
}

TransactionAttributeSourcePointcut 终于上场了,它去找目标类中有没有 @Transaction 注解。

public boolean matches(Method method, Class<?> targetClass) {
    //  TransactionAttributeSource 在这里被拿到了。
    TransactionAttributeSource tas = getTransactionAttributeSource();
    // tas.getTransactionAttribute() 找事务注解。
    return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

AbstractFallBackTransactionAttributeSource 执行了真正的找 @Transaction 注解 的逻辑。

// AbstractFallBackTransactionAttributeSource.java

// targetClass 是 UserService 的类对象,method 是 UserService 中的某个方法。
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
    if (method.getDeclaringClass() == Object.class) {
        return null;
    }

    // method + class 作为 key。
    Object cacheKey = getCacheKey(method, targetClass);
    // 先去缓存中获取下,有没有这个 key 已经解析好的事务属性。
    TransactionAttribute cached = this.attributeCache.get(cacheKey);
    if (cached != null) {
        // 如果能找到,但属性信息是空,那就表示,该方法上没有事务。。
        if (cached == NULL_TRANSACTION_ATTRIBUTE) {
            return null;
        }
        else {
            // 属性信息不为空,那就直接返回事务注解的属性信息。
            return cached;
        }
    }
    else {
        // 缓存里没有就需要自己解析了。
        // 从目标类的方法、目标类、目标类实现的接口的方法、目标类实现的接口上依次查@Transactional注解,
        // 如果有就解析注解的属性,并返回。
        TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
        // 无论解析到的是不是空,都保存到缓存中。
        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;
    }
}
// ---- 核心方法在这里 ----
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
    // 如果 @Transcational 标注在 非 public 方法上,则不解析。
    if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
        return null;
    }
    
    Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

    // First try is the method in the target class.
    // 先检查目标类的方法。它上面如果有 @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.
        // 接着,再检查接口中对应的方法有没有标 @Transactional 注解。
        txAttr = findTransactionAttribute(method);
        if (txAttr != null) {
            return txAttr;
        }
        // Last fallback is the class of the original method.
        // 最后,检查接口上有没有标 @Transactional  注解。
        txAttr = findTransactionAttribute(method.getDeclaringClass());
        if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
            return txAttr;
        }
    }
    // 如果都没有,那就返回 null。
    return null;
}

这里的代码说明了两个事情:

  1. 上面写的找 @Transactional 顺序是对的。
  2. 非 public 方法上标 @Transactional 是无效的,因为源码根本就不解析。

那最后再看一个问题,到底是怎么解析到的 @Transactional 注解。

protected TransactionAttribute findTransactionAttribute(Method method) {
    return determineTransactionAttribute(method);
}
// --- 
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
    for (TransactionAnnotationParser parser : this.annotationParsers) {
        // 这里有个事务注解解析器。
        TransactionAttribute attr = parser.parseTransactionAnnotation(element);
        if (attr != null) {
            return attr;
        }
    }
    return null;
}

// --- SpringTransactionAnnotationParser.java
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
    // 解析的是 Transactional.class 类。
    AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
        element, Transactional.class, false, false);
    if (attributes != null) {
        return parseTransactionAnnotation(attributes);
    }
    else {
        return null;
    }
}

那些切 Uservice 的 增强器就是这么被筛选出来的。

接下来还剩最后一步,为 UserService 创建代理对象…

3.3 为目标对象创建代理对象。

这一块的逻辑和普通的 aop 没有什么区别。

  1. 创建代理工厂。

    ProxyFactory proxyFactory = new ProxyFactory();
    
  2. 将目标对象和它的增强器都 set 到 代理工厂中。

    proxyFactory.setTargetSource(targetSource);
    proxyFactory.addAdvisors(advisors);
    
  3. 代理工厂创建代理对象,并返回。

    proxyFactory.getProxy(getProxyClassLoader())
    

代理对象中个既有目标对象也有目标对象的增强器,当代理对象执行目标方法时,在恰当时机将通知织入,自己是可以实现的。

#4. 代理对象执行目标方法

这部分也是好大的一块内容,单独写一篇博客吧,不然这篇博客得写的老长…

5. 发现一个小问题

我的事务配置是这样的。

@Configuration
@ComponentScan("com.jdbctemplate")
@EnableTransactionManagement
@EnableAspectJAutoProxy(exposeProxy = true)
public class JdbcConfig {
	// ......
}

@EnableAspectJAutoProxy 注入了 AspectJAwareAdvisorAutoProxyCreator 类;

@EnableTransactionManagement 注入了 InfrastructureAdvisorAutoProxyCreator 类;

这两个都是BeanPostProcessor,都可以将 目标对象变成代理对象。

如果两个同时存在,在为事务相关的类创建目标对象时,会使用 AspectJAwareAdvisorAutoProxyCreator 将目标对象变成代理对象。

当去掉 @EnableAspectJAutoProxy 注解时,事务功能也能照常运行。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值