Spring提取@Transactional事务注解的源码解析

声明:本编文章是自己在查看Spring提取@Transactional注解的源码过程中随手记下的笔记,只做了大概流程的记录,未做详细分析,如有错误还请谅解。

《Spring提取@Transactional事务注解的源码解析》

1、事务切面匹配处理类

AopUtils#canApply(Pointcut, Class , boolean)
方法中会调用到 TransactionAttributeSourcePointcut#matches 方法

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();
    IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
    if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
        introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
    }

    Set<Class> classes = new HashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
    classes.add(targetClass);
    for (Class<?> clazz : classes) {
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            //methodMatcher.matches(method, targetClass) 方法会匹配对应的处理类,在Transaction提取的过程中会匹配到:TransactionAttributeSourcePointcut 
            if ((introductionAwareMethodMatcher != null &&
                    introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
                    methodMatcher.matches(method, targetClass)) {
                return true;
            }
        }
    }

    return false;
}

《Spring提取@Transactional事务注解的源码解析》

2、事务切点匹配

TransactionAttributeSourcePointcut#matches

在阅读TransactionAttributeSourcePointcut内的源代码的时候,我们发现该类是一个抽象,但是他确没有实现的子类!!!那么这个类到底在哪被引用了呢?

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

    public boolean matches(Method method, Class targetClass) {

        // 该处调用了 getTransactionAttributeSource() 的抽象方法,但是却没有子类实现这个方法,这是怎么一回事呢?
        TransactionAttributeSource tas = getTransactionAttributeSource();
        return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof TransactionAttributeSourcePointcut)) {
            return false;
        }
        TransactionAttributeSourcePointcut otherPc = (TransactionAttributeSourcePointcut) other;
        return ObjectUtils.nullSafeEquals(getTransactionAttributeSource(), otherPc.getTransactionAttributeSource());
    }

    @Override
    public int hashCode() {
        return TransactionAttributeSourcePointcut.class.hashCode();
    }

    @Override
    public String toString() {
        return getClass().getName() + ": " + getTransactionAttributeSource();
    }


    /**
     * Obtain the underlying TransactionAttributeSource (may be {@code null}).
     * To be implemented by subclasses.
     */
    protected abstract TransactionAttributeSource getTransactionAttributeSource();

}

3、TransactionAttributeSourcePointcut 抽象类的应用

我们怀着上面的疑问全局搜索 TransactionAttributeSourcePointcut 可以在 BeanFactoryTransactionAttributeSourceAdvisor 里面找到如下的代码:

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

    private TransactionAttributeSource transactionAttributeSource;

    // 此处利用了匿名内部类的方式实例化了 TransactionAttributeSourcePointcut 对象,在此我们找到了上面问题的答案。
    private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
        @Override
        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);
    }

    public Pointcut getPointcut() {
        return this.pointcut;
    }

}

3、TransactionAttributeSource 属性的 Bean 定义过程

其实,在实例化 BeanFactoryTransactionAttributeSourceAdvisor 时,Spring 已经为我们的 BeanFactoryTransactionAttributeSourceAdvisor 设置了 TransactionAttributeSource 属性,可以进入 AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer#configureAutoProxyCreator 方法中看源代码:

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

            // 注解事务 transactionAttributeSource Spring 定义的Bean为: AnnotationTransactionAttributeSource 实例
            // Create the TransactionAttributeSource definition.
            RootBeanDefinition sourceDef = new RootBeanDefinition(AnnotationTransactionAttributeSource.class);
            sourceDef.setSource(eleSource);
            sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

            // Create the TransactionInterceptor definition.
            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);

            // create BeanFactoryTransactionAttributeSourceAdvisor Bean 的定义
            // Create the TransactionAttributeSourceAdvisor definition.
            RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
            advisorDef.setSource(eleSource);
            advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            // 设置 transactionAttributeSource 属性
            advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
            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);
        }
    }
}

4、TransactionAttributeSource#getTransactionAttribute 方法的调用过程

通过以上的分析,我们可以确定
TransactionAttributeSourcePointcut#getTransactionAttributeSource 返回的是:AnnotationTransactionAttributeSource 实例,AnnotationTransactionAttributeSource继承自:AbstractFallbackTransactionAttributeSource, 故此TransactionAttributeSourcePointcut#matches 最终会调用到 AbstractFallbackTransactionAttributeSource#getTransactionAttribute 方法

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

    public boolean matches(Method method, Class targetClass) {
        TransactionAttributeSource tas = getTransactionAttributeSource();

        // 最终会调用到 AbstractFallbackTransactionAttributeSource#getTransactionAttribute 方法
        return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
    }

    // 省略其他代码 ……………………
}

再看 AbstractFallbackTransactionAttributeSource#getTransactionAttribute 方法

// 获取事务属性
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
    // First, see if we have a cached value.
    Object cacheKey = getCacheKey(method, targetClass);
    Object 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 (TransactionAttribute) cached;
        }
    }
    else {
        // We need to work it out.  根据 method、targetClass 推算事务属性,TransactionAttribute 
        TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);
        // Put it in the cache.
        if (txAtt == null) {
            this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Adding transactional method '" + method.getName() + "' with attribute: " + txAtt);
            }
            this.attributeCache.put(cacheKey, txAtt);
        }
        return txAtt;
    }
}

5、事务属性的推算过程:

// 推算事务属性,TransactionAttribute 
private TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
    // Don't allow no-public methods as required.
    if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
        return null;
    }

    // Ignore CGLIB subclasses - introspect the actual user class.
    Class<?> userClass = ClassUtils.getUserClass(targetClass);
    // 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 = ClassUtils.getMostSpecificMethod(method, userClass);
    // If we are dealing with method with generic parameters, find the original method.
    specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);

    // 通过上面的分析,findTransactionAttribute 该方法最终会调用到:AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.Class<?>) 

    // First try is the method in the target class. 方式1: 从目标类的方法上找 Transaction注解
    TransactionAttribute txAtt = findTransactionAttribute(specificMethod);
    if (txAtt != null) {
        return txAtt;
    }

    // Second try is the transaction attribute on the target class.  方式2: 从目标类上找 Transaction注解
    txAtt = findTransactionAttribute(specificMethod.getDeclaringClass());
    if (txAtt != null) {
        return txAtt;
    }

    if (specificMethod != method) {// 以上两种方式如果还没有找到 TransactionAttribute 属性,那就要从目标类的接口开始找
        // Fallback is to look at the original method.  方式3:接口的方法上找 Transaction注解
        txAtt = findTransactionAttribute(method);
        if (txAtt != null) {
            return txAtt;
        }
        // Last fallback is the class of the original method.  方式4:接口的类上找 Transaction注解
        return findTransactionAttribute(method.getDeclaringClass());
    }
    return null;
}

6、事务注解属性的解析

AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.Class

7、获取事务注解

public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {

    public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
        //获取 Transactional 注解
        Transactional ann = AnnotationUtils.getAnnotation(ae, Transactional.class);
        if (ann != null) {
            //从 @Transactional 注解上获取事务属性值,并包装成 TransactionAttribute 返回
            return parseTransactionAnnotation(ann);
        }
        else {
            return null;
        }
    }

    public TransactionAttribute parseTransactionAnnotation(Transactional ann) {
        RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
        rbta.setPropagationBehavior(ann.propagation().value());
        rbta.setIsolationLevel(ann.isolation().value());
        rbta.setTimeout(ann.timeout());
        rbta.setReadOnly(ann.readOnly());
        rbta.setQualifier(ann.value());
        ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<RollbackRuleAttribute>();
        Class[] rbf = ann.rollbackFor();
        for (Class rbRule : rbf) {
            RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
            rollBackRules.add(rule);
        }
        String[] rbfc = ann.rollbackForClassName();
        for (String rbRule : rbfc) {
            RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
            rollBackRules.add(rule);
        }
        Class[] nrbf = ann.noRollbackFor();
        for (Class rbRule : nrbf) {
            NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
            rollBackRules.add(rule);
        }
        String[] nrbfc = ann.noRollbackForClassName();
        for (String rbRule : nrbfc) {
            NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
            rollBackRules.add(rule);
        }
        rbta.getRollbackRules().addAll(rollBackRules);
        return rbta;
    }

    @Override
    public boolean equals(Object other) {
        return (this == other || other instanceof SpringTransactionAnnotationParser);
    }

    @Override
    public int hashCode() {
        return SpringTransactionAnnotationParser.class.hashCode();
    }

}
    原文作者:Spring MVC
    原文地址: https://blog.csdn.net/dalinsi/article/details/53215041
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞