Spring声明式事务源码解析

1. 事务基本流程

  1. 注册事务相关的beanDefinition。
  2. 为需要执行声明式事务的bean生成动态代理。
  3. 调用目标方法时,优先通过代理调用事务的增强方法。
  4. 在事务的增强方法里选择事务管理器,控制事务的开启、回滚、提交。

2. 事务的流程详解(springboot项目,以注解形式为例分析)

2.1 注册事务相关的beanDefinition

2.1.1 通过TransactionAutoConfiguration自动装配事务功能

springboot通过TransactionAutoConfiguration类对事务进行自动装配,最关键的开启事务的注解为@EnableTransactionManagement。

2.1.2 通过EnableTransactionManagement注解开启事务功能

在@EnableTransactionManagement中,导入了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;
}

2.1.3 导入事务相关的核心类

由于@EnableTransactionManagement注解默认的模式为PROXY,所以TransactionManagementConfigurationSelector类会导入AutoProxyRegistrar类、ProxyTransactionManagementConfiguration类。AutoProxyRegistrar类的作用为注册实现了BeanPostProcessor接口的beanDifinition,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:
             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);
    }
}

2.1.4 AutoProxyRegistrar类注册生成动态代理的BeanPostProcessor

AutoProxyRegistrar类通过AopConfigUtils.registerAutoProxyCreatorIfNecessary()方法向spring容器中注册了InfrastructureAdvisorAutoProxyCreator类的beanDifinition。InfrastructureAdvisorAutoProxyCreator类实现了BeanPostProcessor接口,该接口会在bean的生命周期方法中进行回调(通过回调方法可以为声明事务的类生成动态代理,从而为该类实现事务增强)。

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

public abstract class AopConfigUtils {

    @Nullable
    public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
       return registerAutoProxyCreatorIfNecessary(registry, null);
    }

    @Nullable
    public static BeanDefinition registerAutoProxyCreatorIfNecessary(
          BeanDefinitionRegistry registry, @Nullable Object source) {
       return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
    }
}

2.1.5 ProxyTransactionManagementConfiguration类注册了3个事务处理核心类

ProxyTransactionManagementConfiguration类包含有3个打了@bean注解的方法,这3个方法返回的对象会生成bean注册进spirng容器。这3个类分别为TransactionAttributeSource、TransactionInterceptor和BeanFactoryTransactionAttributeSourceAdvisor(AOP中有3个概念为pointCut、advice、advisor,在后续的分析里我们会发现上述三个类与AOP中的概念一一对应)。

@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) {

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

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

2.2 为需要执行声明式事务的类生成动态代理

2.2.1 执行BeanPostProcessor.postProcessAfterInitialization方法

InfrastructureAdvisorAutoProxyCreator类的抽象基类(AbstractAutoProxyCreator)实现了BeanPostProcessor.postProcessAfterInitialization接口方法,该方法会在bean的初始化后调用。

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
       implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    @Override
    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;
    }
}

2.2.2 检查初始化后的bean是否存在满足条件的advisor,存在则为其生成动态代理

进入wrapIfNecessary方法,调用getAdvicesAndAdvisorsForBean方法检查该bean是否存在满足条件的advisor,如果存在,则调用createProxy为其创建动态代理。

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

    // Create proxy if we have advice.
    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;
}

2.2.3 查找满足条件的advisor

在getAdvicesAndAdvisorsForBean方法中继续调用findEligibleAdvisors方法。

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方法中第一调用findCandidateAdvisors查找所有参与候选的advisor。然后在从所有参与候选的advisor中挑选出适用于目标bean的advisor。

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
       eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

2.2.3.1 如何查找所有候选的advisor

先调用基类的findCandidateAdvisors方法找出所有spring中注册的advisors,然后调用aspectJAdvisorsBuilder.buildAspectJAdvisors方法解析出切面中的advisor(AOP中的重点内容,本文不做解析)

protected List<Advisor> findCandidateAdvisors() {
    // Add all the Spring advisors found according to superclass rules.
    List<Advisor> advisors = super.findCandidateAdvisors();
    // Build Advisors for all AspectJ aspects in the bean factory.
    if (this.aspectJAdvisorsBuilder != null) {
       advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }
    return advisors;
}

基类的findCandidateAdvisors方法中会调用到BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans方法,在该方法中会查询spring中所有Advisor接口的实现类,并从容器中获取bean(在BeanPostProcessor.postProcessBeforeInitialization便会调用该方法完成advisor bean的创建,在这里直接根据缓存中的advisorNames在spring容器中取出对应的advisor bean)。由于BeanFactoryTransactionAttributeSourceAdvisor也是Advisor接口的实现类,所以在这里也会被获取到。

public List<Advisor> findAdvisorBeans() {
    String[] advisorNames = this.cachedAdvisorBeanNames;
    if (advisorNames == null) {
       advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
             this.beanFactory, Advisor.class, true, false);
       this.cachedAdvisorBeanNames = advisorNames;
    }
    if (advisorNames.length == 0) {
       return new ArrayList<>();
    }

    List<Advisor> advisors = new ArrayList<>();
    for (String name : advisorNames) {
       if (isEligibleBean(name)) {
          if (this.beanFactory.isCurrentlyInCreation(name)) {
          }
          else {
             try {
                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)) {
                      continue;
                   }
                }
                throw ex;
             }
          }
       }
    }
    return advisors;
}

2.2.3.2 检查满足bean条件的advisor

findAdvisorsThatCanApply方法中会调用AopUtils#findAdvisorsThatCanApply方法,该方法会遍历candidateAdvisors,检查是否满足条件

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) {
          // already processed
          continue;
       }
       if (canApply(candidate, clazz, hasIntroductions)) {
          eligibleAdvisors.add(candidate);
       }
    }
    return eligibleAdvisors;
}

继续跟入canApply方法,BeanFactoryTransactionAttributeSourceAdvisor也是PointcutAdvisor的实现类,所以会继续执行canApply方法,第一个参数为BeanFactoryTransactionAttributeSourceAdvisor的pointcut属性。

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 {
       // It doesn t have a pointcut so we assume it applies.
       return true;
    }
}

BeanFactoryTransactionAttributeSourceAdvisor的pointcut属性是内部创建的TransactionAttributeSourcePointcut对象,该对象getTransactionAttributeSource方法返回的对象就是在ProxyTransactionManagementConfiguration类中为BeanFactoryTransactionAttributeSourceAdvisor对象赋值的TransactionAttributeSource。

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

    @Nullable
    private TransactionAttributeSource transactionAttributeSource;

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

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

接着跟入canApply方法,该方法会将targetClass的所有基类、接口类汇总成类集合,并遍历类集合中的每一个method,依次使用Pointcut的methodMatcher.match方法检查method是否满足条件,任意一个method满足条件即满足条件。

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.matches(method, targetClass)) {
             return true;
          }
       }
    }

    return false;
}

TransactionAttributeSourcePointcut的methodMatcher.match会先拿到TransactionAttributeSource对象,在使用TransactionAttributeSource检查方法是否满足条件

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

    protected TransactionAttributeSourcePointcut() {
       setClassFilter(new TransactionAttributeSourceClassFilter());
    }

    @Override
    public boolean matches(Method method, Class<?> targetClass) {
       TransactionAttributeSource tas = getTransactionAttributeSource();
       return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
    }
}

继续跟入AbstractFallbackTransactionAttributeSource#getTransactionAttribute,核心逻辑在computeTransactionAttribute方法中

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

    // First, see if we have a cached value.
    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 {
       // We need to work it out.
       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 dta = (DefaultTransactionAttribute) txAttr;
             dta.setDescriptor(methodIdentification);
             dta.resolveAttributeStrings(this.embeddedValueResolver);
          }
          this.attributeCache.put(cacheKey, txAttr);
       }
       return txAttr;
    }
}

继续跟入computeTransactionAttribute方法,其核心逻辑在findTransactionAttribute方法中

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

    // The method may be on an interface, but we need attributes from the target class.
    // If the target class is null, the method will be unchanged.
    Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

    // First try is the method in the target class.
    TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
    if (txAttr != null) {
       return txAttr;
    }

    // Second try is the transaction attribute on the target class.
    txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
    if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
       return txAttr;
    }

    if (specificMethod != method) {
       // Fallback is to look at the original method.
       txAttr = findTransactionAttribute(method);
       if (txAttr != null) {
          return txAttr;
       }
       // Last fallback is the class of the original method.
       txAttr = findTransactionAttribute(method.getDeclaringClass());
       if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
          return txAttr;
       }
    }

    return null;
}

跟入findTransactionAttribute方法,进而跟入determineTransactionAttribute方法。会发现这里使用parser解析方法上的TransactionAttribute属性,这里的parser使用的是SpringTransactionAnnotationParser(检查条件满足逻辑已比较复杂,此处感兴趣自行跟入)

protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
    for (TransactionAnnotationParser parser : this.annotationParsers) {
       TransactionAttribute attr = parser.parseTransactionAnnotation(element);
       if (attr != null) {
          return attr;
       }
    }
    return null;
}

终于在解析方法中看到检查条件是否满足即检查(基类、目标类、接口类)上是否有标记Transactional注解。

@SuppressWarnings("serial")
public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {

    @Override
    public boolean isCandidateClass(Class<?> targetClass) {
       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;
       }
    }
}

2.2.4 生成动态代理

跟入AbstractAutoProxyCreator#createProxy,构造ProxyFactory对象,

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()) {
       // Explicit handling of JDK proxy targets and lambdas (for introduction advice scenarios)
       if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {
          // Must allow for introductions; can t just set interfaces to the proxy s interfaces only.
          for (Class<?> ifc : beanClass.getInterfaces()) {
             proxyFactory.addInterface(ifc);
          }
       }
    }
    else {
       // No proxyTargetClass flag enforced, let s apply our default checks...
       if (shouldProxyTargetClass(beanClass, beanName)) {
          proxyFactory.setProxyTargetClass(true);
       }
       else {
          evaluateProxyInterfaces(beanClass, proxyFactory);
       }
    }

    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    proxyFactory.addAdvisors(advisors);
    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
       proxyFactory.setPreFiltered(true);
    }

    // Use original ClassLoader if bean class not locally loaded in overriding class loader
    ClassLoader classLoader = getProxyClassLoader();
    if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
       classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
    }
    return proxyFactory.getProxy(classLoader);
}

跟入proxyFactory.getProxy方法,在该方法中第一会选择创建动态代理的方式(JDK动态代理、CGLIB动态代理),并将AdvisedSupport对象(携带advisor、目标类)传入动态代理类。

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    if (!NativeDetector.inNativeImage() &&
          (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
       Class<?> targetClass = config.getTargetClass();
       if (targetClass == null) {
          throw new AopConfigException("TargetSource cannot determine target class: " +
                "Either an interface or a target is required for proxy creation.");
       }
       if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
          return new JdkDynamicAopProxy(config);
       }
       return new ObjenesisCglibAopProxy(config);
    }
    else {
       return new JdkDynamicAopProxy(config);
    }
}

选择动态代理方式后,便按照相应的方式生成动态代理对象返回(以CGLIB动态代理为例)

public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isTraceEnabled()) {
       logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
    }

    try {
       Class<?> rootClass = this.advised.getTargetClass();
       Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

       Class<?> proxySuperClass = rootClass;
       if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
          proxySuperClass = rootClass.getSuperclass();
          Class<?>[] additionalInterfaces = rootClass.getInterfaces();
          for (Class<?> additionalInterface : additionalInterfaces) {
             this.advised.addInterface(additionalInterface);
          }
       }

       // Validate the class, writing log messages as necessary.
       validateClassIfNecessary(proxySuperClass, classLoader);

       // Configure 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));

       Callback[] callbacks = getCallbacks(rootClass);
       Class<?>[] types = new Class<?>[callbacks.length];
       for (int x = 0; x < types.length; x++) {
          types[x] = callbacks[x].getClass();
       }
       // fixedInterceptorMap only populated at this point, after getCallbacks call above
       enhancer.setCallbackFilter(new ProxyCallbackFilter(
             this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
       enhancer.setCallbackTypes(types);

       // Generate the proxy class and create a proxy instance.
       return createProxyClassAndInstance(enhancer, callbacks);
    }
    catch (CodeGenerationException | IllegalArgumentException ex) {
       throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
             ": Common causes of this problem include using a final class or a non-visible class",
             ex);
    }
    catch (Throwable ex) {
       // TargetSource.getTarget() failed
       throw new AopConfigException("Unexpected AOP exception", ex);
    }
}

动态代理的回调方法,与事务增强有关的回调为DynamicAdvisedInterceptor,可以看到创建DynamicAdvisedInterceptor时把advised(携带advisor、目标类)作为参数传入构造函数。

private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
    // Parameters used for optimization choices...
    boolean exposeProxy = this.advised.isExposeProxy();
    boolean isFrozen = this.advised.isFrozen();
    boolean isStatic = this.advised.getTargetSource().isStatic();

    // Choose an "aop" interceptor (used for AOP calls).
    Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

    // Choose a "straight to target" interceptor. (used for calls that are
    // unadvised but can return this). May be required to expose the proxy.
    Callback targetInterceptor;
    if (exposeProxy) {
       targetInterceptor = (isStatic ?
             new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
             new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
    }
    else {
       targetInterceptor = (isStatic ?
             new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
             new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
    }

    // Choose a "direct to target" dispatcher (used for
    // unadvised calls to static targets that cannot return this).
    Callback targetDispatcher = (isStatic ?
          new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());

    Callback[] mainCallbacks = new Callback[] {
          aopInterceptor,  // for normal advice
          targetInterceptor,  // invoke target without considering advice, if optimized
          new SerializableNoOp(),  // no override for methods mapped to this
          targetDispatcher, this.advisedDispatcher,
          new EqualsInterceptor(this.advised),
          new HashCodeInterceptor(this.advised)
    };

    Callback[] callbacks;

    // If the target is a static one and the advice chain is frozen,
    // then we can make some optimizations by sending the AOP calls
    // direct to the target using the fixed chain for that method.
    if (isStatic && isFrozen) {
       Method[] methods = rootClass.getMethods();
       Callback[] fixedCallbacks = new Callback[methods.length];
       this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);

       // TODO: small memory optimization here (can skip creation for methods with no advice)
       for (int x = 0; x < methods.length; x++) {
          Method method = methods[x];
          List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
          fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
                chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
          this.fixedInterceptorMap.put(method, x);
       }

       // Now copy both the callbacks from mainCallbacks
       // and fixedCallbacks into the callbacks array.
       callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
       System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
       System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
       this.fixedInterceptorOffset = mainCallbacks.length;
    }
    else {
       callbacks = mainCallbacks;
    }
    return callbacks;
}

2.3 调用目标方法时,优先通过代理调用事务的增强方法。

2.3.1 调用目标方法时,优先进入动态代理的回调方法

private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

    private final AdvisedSupport advised;

    public DynamicAdvisedInterceptor(AdvisedSupport advised) {
       this.advised = advised;
    }

    @Override
    @Nullable
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
       Object oldProxy = null;
       boolean setProxyContext = false;
       Object target = null;
       TargetSource targetSource = this.advised.getTargetSource();
       try {
          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);
          Object retVal;
          // Check whether we only have one InvokerInterceptor: that is,
          // no real advice, but just reflective invocation of the target.
          if (chain.isEmpty() && CglibMethodInvocation.isMethodProxyCompatible(method)) {
             // 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 = invokeMethod(target, method, argsToUse, methodProxy);
          }
          else {
             // We need to create a method invocation...
             retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
          }
          retVal = processReturnType(proxy, target, method, retVal);
          return retVal;
       }
       finally {
          if (target != null && !targetSource.isStatic()) {
             targetSource.releaseTarget(target);
          }
          if (setProxyContext) {
             // Restore old proxy.
             AopContext.setCurrentProxy(oldProxy);
          }
       }
    }
}

2.3.2 通过advised获取interceptorList

跟入this.advised.getInterceptorsAndDynamicInterceptionAdvice方法,在方法内部获取所有的advisors,即为advised内部的advisors。并遍历advisor,依次生成MethodInterceptor数组添加进interceptorList。

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
       Advised config, Method method, @Nullable Class<?> targetClass) {

    // This is somewhat tricky... We have to process introductions first,
    // but we need to preserve order in the ultimate list.
    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
    Advisor[] advisors = config.getAdvisors();
    List<Object> interceptorList = new ArrayList<>(advisors.length);
    Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
    Boolean hasIntroductions = null;

    for (Advisor advisor : advisors) {
       if (advisor instanceof PointcutAdvisor) {
          // Add it conditionally.
          PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
          if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
             MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
             boolean match;
             if (mm instanceof IntroductionAwareMethodMatcher) {
                if (hasIntroductions == null) {
                   hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
                }
                match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
             }
             else {
                match = mm.matches(method, actualClass);
             }
             if (match) {
                MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                if (mm.isRuntime()) {
                   // Creating a new object instance in the getInterceptors() method
                   // isn t a problem as we normally cache created chains.
                   for (MethodInterceptor interceptor : interceptors) {
                      interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                   }
                }
                else {
                   interceptorList.addAll(Arrays.asList(interceptors));
                }
             }
          }
       }
       else if (advisor instanceof IntroductionAdvisor) {
          IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
          if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
             Interceptor[] interceptors = registry.getInterceptors(advisor);
             interceptorList.addAll(Arrays.asList(interceptors));
          }
       }
       else {
          Interceptor[] interceptors = registry.getInterceptors(advisor);
          interceptorList.addAll(Arrays.asList(interceptors));
       }
    }

    return interceptorList;
}

跟进registry.getInterceptors(advisor)方法,获取advisor的advice对象,并将其转换为MethodInterceptor数组返回。事务的advisor为BeanFactoryTransactionAttributeSourceAdvisor类型,而其advice对象为TransactionInterceptor类型,所以返回的Interceptor为一个TransactionInterceptor包装类型。

public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
    List<MethodInterceptor> interceptors = new ArrayList<>(3);
    Advice advice = advisor.getAdvice();
    if (advice instanceof MethodInterceptor) {
       interceptors.add((MethodInterceptor) advice);
    }
    for (AdvisorAdapter adapter : this.adapters) {
       if (adapter.supportsAdvice(advice)) {
          interceptors.add(adapter.getInterceptor(advisor));
       }
    }
    if (interceptors.isEmpty()) {
       throw new UnknownAdviceTypeException(advisor.getAdvice());
    }
    return interceptors.toArray(new MethodInterceptor[0]);
}

2.3.3 通过责任链依次调用interceptor的invoke方法

将生成的interceptorList传入CglibMethodInvocation,通过责任链依次调用其interceptor方法,其核心逻辑控制在其基类的ReflectiveMethodInvocation#proceed方法。依次调用interceptor的invoke方法,直到最后直接调用切点方法(即被代理类的原始方法)。

public Object proceed() throws Throwable {
    // We start with an index of -1 and increment early.
    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();
       }
    }
    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);
    }
}

2.3.4 调用事务的增强处理器方法

TransactionInterceptor作为其中一个interceptor,在责任链调用时会调用其invoke方法。

@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
    // Work out the target class: may be {@code null}.
    // The TransactionAttributeSource should be passed the target class
    // as well as the method, which may be from an interface.
    Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

    // Adapt to TransactionAspectSupport s invokeWithinTransaction...
    return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
       @Override
       @Nullable
       public Object proceedWithInvocation() throws Throwable {
          return invocation.proceed();
       }
       @Override
       public Object getTarget() {
          return invocation.getThis();
       }
       @Override
       public Object[] getArguments() {
          return invocation.getArguments();
       }
    });
}

2.4 使用事务管理器控制事务执行。

2.4.1 查找事务属性

第一获取TransactionAttributeSource,这个对象为最初在spring容器注册的bean对象。在创建动态代理时,也是使用此类解析方法上的事务注解,故此类的缓存中保存有方法与事务属性的映射关系。

protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
       final InvocationCallback invocation) throws Throwable {

    // If the transaction attribute is null, the method is non-transactional.
    TransactionAttributeSource tas = getTransactionAttributeSource();
    final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
    final TransactionManager tm = determineTransactionManager(txAttr);

    PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

    if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
       // Standard transaction demarcation with getTransaction and commit/rollback calls.
       TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

       Object retVal;
       try {
          // This is an around advice: Invoke the next interceptor in the chain.
          // This will normally result in a target object being invoked.
          retVal = invocation.proceedWithInvocation();
       }
       catch (Throwable ex) {
          // target invocation exception
          completeTransactionAfterThrowing(txInfo, ex);
          throw ex;
       }
       finally {
          cleanupTransactionInfo(txInfo);
       }

       if (retVal != null && 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 {
      // ...
       return result;
    }
}

2.4.2 根据事务属性选择事务管理器

如果事务的属性上有指定事务管理器的名字,则通过名字查找事务管理器。如果事务属性未指定事务管理器,则根据transactionManagerBeanName查找事务管理器。如果transactionManagerBeanName也无指定,则去transactionManagerCache查找默认的事务管理器,如果还未找到,则去spring容器中查询TransactionManager类的bean作为默认事务管理器。

protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
    // Do not attempt to lookup tx manager if no tx attributes are set
    if (txAttr == null || this.beanFactory == null) {
       return getTransactionManager();
    }

    String qualifier = txAttr.getQualifier();
    if (StringUtils.hasText(qualifier)) {
       return determineQualifiedTransactionManager(this.beanFactory, qualifier);
    }
    else if (StringUtils.hasText(this.transactionManagerBeanName)) {
       return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
    }
    else {
       TransactionManager defaultTransactionManager = getTransactionManager();
       if (defaultTransactionManager == null) {
          defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
          if (defaultTransactionManager == null) {
             defaultTransactionManager = this.beanFactory.getBean(TransactionManager.class);
             this.transactionManagerCache.putIfAbsent(
                   DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
          }
       }
       return defaultTransactionManager;
    }
}

2.4.3 控制事务执行

开启事务,继续执行责任链,责任链执行完毕则会执行到目标方法。若方法正常执行结束则提交事务,否则则回滚事务。

    TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

       Object retVal;
       try {
          // This is an around advice: Invoke the next interceptor in the chain.
          // This will normally result in a target object being invoked.
          retVal = invocation.proceedWithInvocation();
       }
       catch (Throwable ex) {
          // target invocation exception
          completeTransactionAfterThrowing(txInfo, ex);
          throw ex;
       }
       finally {
          cleanupTransactionInfo(txInfo);
       }

       if (retVal != null && 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);

3.事务总结

本文完整的分析了事务执行的核心流程,总结下来事务的执行依赖bean的生命周期回调和几个事务相关的核心类。当开启事务功能后,会向容器注册一个beanPostProcessor,在每个bean初始化完成时调用beanPostProcessor的回调方法,回调方法里会检查该类是否存在满足条件的advisor(BeanFactoryTransactionAttributeSourceAdvisor),满足事务条件(通过TransactionAttributeSource解析检查)的bean则会为其生成动态代理。在执行目标方法时,第一会执行动态代理的回调方法,在回调方法里获取目标方法的事务增强类(TransactionInterceptor)并执行其回调,在回调中控制事务的执行。

© 版权声明

相关文章

暂无评论

none
暂无评论...