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

    xiaoxiao2021-11-29  52

    声明:本编文章是自己在查看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; }

    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(); } }
    转载请注明原文地址: https://ju.6miu.com/read-678578.html

    最新回复(0)