spring事务管理源码解析之其余

本文转自“天河聊技术”微信公众号spring

 

说在前面微信

基于注解的spring声明式事务管理源码解析已经完毕了,第一篇文章中提到spring事务管理模式有两种形式一种是proxy,一种是aspectj,基于proxy已经解析完毕了,默认的也是proxy,声明式事务管理配置一种是基于注解,一种是基于xml配置文件的,最后再补充下基于aspectj这种事务模式和基于xml配置的声明式事务管理的源码解析。app

正文ide

基于aspectj的声明事务管理模式源码解析ui

找到这个方法org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser#parsethis

@Override
   @Nullable
   public BeanDefinition parse(Element element, ParserContext parserContext) {
//    注册事务监听器工厂
      registerTransactionalEventListenerFactory(parserContext);
//    获取模式属性
      String mode = element.getAttribute("mode");
      if ("aspectj".equals(mode)) {
         // mode="aspectj"
         registerTransactionAspect(element, parserContext);
      }
      else {
         // mode="proxy"
         AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
      }
      return null;
   }
if ("aspectj".equals(mode)) {
   // mode="aspectj"
   registerTransactionAspect(element, parserContext);

进入到这个方法spa

org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser#registerTransactionAspectorm

private void registerTransactionAspect(Element element, ParserContext parserContext) {
      String txAspectBeanName = TransactionManagementConfigUtils.TRANSACTION_ASPECT_BEAN_NAME;
      String txAspectClassName = TransactionManagementConfigUtils.TRANSACTION_ASPECT_CLASS_NAME;
      if (!parserContext.getRegistry().containsBeanDefinition(txAspectBeanName)) {
         RootBeanDefinition def = new RootBeanDefinition();
         def.setBeanClassName(txAspectClassName);
         def.setFactoryMethodName("aspectOf");
//       注册事务管理器到bean定义中
         registerTransactionManager(element, def);
//       注册AnnotationTransactionAspect bean定义
         parserContext.registerBeanComponent(new BeanComponentDefinition(def, txAspectBeanName));
      }
   }

进入到这个类xml

org.springframework.transaction.aspectj.AnnotationTransactionAspect对象

public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {

   public AnnotationTransactionAspect() {
//    初始化注解事务资源
      super(new AnnotationTransactionAttributeSource(false));
   }

   /**
    * Matches the execution of any public method in a type with the Transactional将类型中的任何公共方法的执行与事务匹配
    * annotation, or any subtype of a type with the Transactional annotation.注释,或具备事务注释的类型的任何子类型。
    */
   private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
      execution(public * ((@Transactional *)+).*(..)) && within(@Transactional *);

   /**
    * Matches the execution of any method with the Transactional annotation.将任何方法的执行与事务注释匹配。
    */
   private pointcut executionOfTransactionalMethod() :
      execution(@Transactional * *(..));

   /**
    * Definition of pointcut from super aspect - matched join points从超方面匹配的链接点定义切入点
    * will have Spring transaction management applied.将应用Spring事务管理。
    */
   protected pointcut transactionalMethodExecution(Object txObject) :
      (executionOfAnyPublicMethodInAtTransactionalType() || executionOfTransactionalMethod() ) && this(txObject);

}

基于aop标签配置的声明式事务源码解析

找到这个方法

org.springframework.transaction.config.TxAdviceBeanDefinitionParser#doParse

@Override
   protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
//    构造事务管理器对象
      builder.addPropertyReference("transactionManager", TxNamespaceHandler.getTransactionManagerName(element));

//    获取<tx:attributes>子节点
      List<Element> txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES_ELEMENT);
//    只能有一个<tx:attributes>节点
      if (txAttributes.size() > 1) {
         parserContext.getReaderContext().error(
               "Element <attributes> is allowed at most once inside element <advice>", element);
      }
      else if (txAttributes.size() == 1) {
         // Using attributes source.
         Element attributeSourceElement = txAttributes.get(0);
//       解析<tx:attributes>标签
         RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext);
         builder.addPropertyValue("transactionAttributeSource", attributeSourceDefinition);
      }
      else {
         // Assume annotations source.
         builder.addPropertyValue("transactionAttributeSource",
               new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"));
      }
   }
private RootBeanDefinition parseAttributeSource(Element attrEle, ParserContext parserContext) {
//    获取<tx:method子节点
      List<Element> methods = DomUtils.getChildElementsByTagName(attrEle, METHOD_ELEMENT);
      ManagedMap<TypedStringValue, RuleBasedTransactionAttribute> transactionAttributeMap =
            new ManagedMap<>(methods.size());
      transactionAttributeMap.setSource(parserContext.extractSource(attrEle));

      for (Element methodEle : methods) {
//       获取name属性
         String name = methodEle.getAttribute(METHOD_NAME_ATTRIBUTE);
         TypedStringValue nameHolder = new TypedStringValue(name);
         nameHolder.setSource(parserContext.extractSource(methodEle));

         RuleBasedTransactionAttribute attribute = new RuleBasedTransactionAttribute();
//       获取事务传播机制
         String propagation = methodEle.getAttribute(PROPAGATION_ATTRIBUTE);
//       获取事务隔离级别
         String isolation = methodEle.getAttribute(ISOLATION_ATTRIBUTE);
//       获取事务超时参数
         String timeout = methodEle.getAttribute(TIMEOUT_ATTRIBUTE);
//       获取事务只读属性
         String readOnly = methodEle.getAttribute(READ_ONLY_ATTRIBUTE);
         if (StringUtils.hasText(propagation)) {
            attribute.setPropagationBehaviorName(RuleBasedTransactionAttribute.PREFIX_PROPAGATION + propagation);
         }
         if (StringUtils.hasText(isolation)) {
            attribute.setIsolationLevelName(RuleBasedTransactionAttribute.PREFIX_ISOLATION + isolation);
         }
         if (StringUtils.hasText(timeout)) {
            try {
               attribute.setTimeout(Integer.parseInt(timeout));
            }
            catch (NumberFormatException ex) {
               parserContext.getReaderContext().error("Timeout must be an integer value: [" + timeout + "]", methodEle);
            }
         }
         if (StringUtils.hasText(readOnly)) {
            attribute.setReadOnly(Boolean.valueOf(methodEle.getAttribute(READ_ONLY_ATTRIBUTE)));
         }

         List<RollbackRuleAttribute> rollbackRules = new LinkedList<>();
         if (methodEle.hasAttribute(ROLLBACK_FOR_ATTRIBUTE)) {
//          获取事务回滚的异常配置
            String rollbackForValue = methodEle.getAttribute(ROLLBACK_FOR_ATTRIBUTE);
            addRollbackRuleAttributesTo(rollbackRules,rollbackForValue);
         }
         if (methodEle.hasAttribute(NO_ROLLBACK_FOR_ATTRIBUTE)) {
//          获取不回滚事务的异常类型
            String noRollbackForValue = methodEle.getAttribute(NO_ROLLBACK_FOR_ATTRIBUTE);
            addNoRollbackRuleAttributesTo(rollbackRules,noRollbackForValue);
         }
         attribute.setRollbackRules(rollbackRules);

         transactionAttributeMap.put(nameHolder, attribute);
      }

      RootBeanDefinition attributeSourceDefinition = new RootBeanDefinition(NameMatchTransactionAttributeSource.class);
      attributeSourceDefinition.setSource(parserContext.extractSource(attrEle));
      attributeSourceDefinition.getPropertyValues().add("nameMap", transactionAttributeMap);
      return attributeSourceDefinition;
   }
private void addRollbackRuleAttributesTo(List<RollbackRuleAttribute> rollbackRules, String rollbackForValue) {
//    能够配置多个异常,用,分开
      String[] exceptionTypeNames = StringUtils.commaDelimitedListToStringArray(rollbackForValue);
      for (String typeName : exceptionTypeNames) {
         rollbackRules.add(new RollbackRuleAttribute(StringUtils.trimWhitespace(typeName)));
      }
   }

   private void addNoRollbackRuleAttributesTo(List<RollbackRuleAttribute> rollbackRules, String noRollbackForValue) {
//    能够配置多个异常,用,分开
      String[] exceptionTypeNames = StringUtils.commaDelimitedListToStringArray(noRollbackForValue);
      for (String typeName : exceptionTypeNames) {
         rollbackRules.add(new NoRollbackRuleAttribute(StringUtils.trimWhitespace(typeName)));
      }
   }

下面的逻辑都同样了,都走的是一个事务拦截器拦截事务方法,解析事务属性,开启事务进行提交或者回滚。

说到最后

本次解析仅表明我的看法,仅供参考。

相关文章
相关标签/搜索