和 aop 几乎一样,在解析 xml 文件的时候,需要找到特定标签的解析类。

获取命名空间处理器

  1. @Nullable
  2. public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
  3. // 参数校验
  4. String namespaceUri = getNamespaceURI(ele);
  5. if (namespaceUri == null) {
  6. return null;
  7. }
  8. // 获取自定义标签解析器
  9. NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
  10. if (handler == null) {
  11. error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
  12. return null;
  13. }
  14. return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
  15. }

这里用到的是 TxNamespaceHandler,可见

  1. 用于解析 标签的工具为 TxAdviceBeanDefinitionParser
  2. 用于解析 标签的工具为 AnnotationDrivenBeanDefinitionParser
  3. 用于解析 jta-transaction-manager 标签的工具为 JtaTransactionManagerBeanDefinitionParser ```java public class TxNamespaceHandler extends NamespaceHandlerSupport {

    static final String TRANSACTION_MANAGER_ATTRIBUTE = “transaction-manager”;

    static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = “transactionManager”;

  1. static String getTransactionManagerName(Element element) {
  2. return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
  3. element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
  4. }
  5. @Override
  6. public void init() {
  7. registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
  8. registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
  9. registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
  10. }

}

  1. <a name="v4Ps1"></a>
  2. ## 解析 tx 标签
  3. 先来到父类标签解析的方法,得到解析工具 TxAdviceBeanDefinitionParser<br />spring-beans | org.springframework.beans.factory.xml.NamespaceHandlerSupport#parse
  4. ```java
  5. @Override
  6. @Nullable
  7. public BeanDefinition parse(Element element, ParserContext parserContext) {
  8. // 得到TxAdviceBeanDefinitionParser
  9. BeanDefinitionParser parser = findParserForElement(element, parserContext);
  10. return (parser != null ? parser.parse(element, parserContext) : null);
  11. }

来到解析工具父类的解析方法 image.png
org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parse

  1. @Override
  2. @Nullable
  3. public final BeanDefinition parse(Element element, ParserContext parserContext) {
  4. // 得到 RootBeanDefinition
  5. AbstractBeanDefinition definition = parseInternal(element, parserContext);
  6. if (definition != null && !parserContext.isNested()) {
  7. try {
  8. String id = resolveId(element, definition, parserContext);
  9. if (!StringUtils.hasText(id)) {
  10. parserContext.getReaderContext().error(
  11. "Id is required for element '" + parserContext.getDelegate().getLocalName(element)
  12. + "' when used as a top-level tag", element);
  13. }
  14. String[] aliases = null;
  15. if (shouldParseNameAsAliases()) {
  16. String name = element.getAttribute(NAME_ATTRIBUTE);
  17. if (StringUtils.hasLength(name)) {
  18. aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
  19. }
  20. }
  21. BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
  22. registerBeanDefinition(holder, parserContext.getRegistry());
  23. if (shouldFireEvents()) {
  24. BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
  25. postProcessComponentDefinition(componentDefinition);
  26. parserContext.registerComponent(componentDefinition);
  27. }
  28. }
  29. catch (BeanDefinitionStoreException ex) {
  30. String msg = ex.getMessage();
  31. parserContext.getReaderContext().error((msg != null ? msg : ex.toString()), element);
  32. return null;
  33. }
  34. }
  35. return definition;
  36. }

parseInternal |

解析得到bean定义,这里解析的是
org.springframework.beans.factory.support.AbstractBeanDefinition

  1. protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
  2. // bean定义构建器,创建一个空的 AbstractBeanDefinition
  3. BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
  4. String parentName = getParentName(element);
  5. if (parentName != null) {
  6. builder.getRawBeanDefinition().setParentName(parentName);
  7. }
  8. // 获取标签对应的 bean Class
  9. // org.springframework.transaction.interceptor.TransactionInterceptor
  10. Class<?> beanClass = getBeanClass(element);
  11. if (beanClass != null) {
  12. builder.getRawBeanDefinition().setBeanClass(beanClass);
  13. } else {
  14. String beanClassName = getBeanClassName(element);
  15. if (beanClassName != null) {
  16. builder.getRawBeanDefinition().setBeanClassName(beanClassName);
  17. }
  18. }
  19. builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
  20. BeanDefinition containingBd = parserContext.getContainingBeanDefinition();
  21. if (containingBd != null) {
  22. // Inner bean definition must receive same scope as containing bean.
  23. builder.setScope(containingBd.getScope());
  24. }
  25. // 是否懒加载,默认false
  26. if (parserContext.isDefaultLazyInit()) {
  27. // Default-lazy-init applies to custom bean definitions as well.
  28. builder.setLazyInit(true);
  29. }
  30. doParse(element, parserContext, builder);
  31. return builder.getBeanDefinition();
  32. }

doParse |

这里解析的是
org.springframework.transaction.config.TxAdviceBeanDefinitionParser#doParse

  1. @Override
  2. protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
  3. builder.addPropertyReference("transactionManager", TxNamespaceHandler.getTransactionManagerName(element));
  4. // 获取子标签
  5. List<Element> txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES_ELEMENT);
  6. if (txAttributes.size() > 1) {
  7. // 异常。只能有一个这样的标签
  8. parserContext.getReaderContext().error(
  9. "Element <attributes> is allowed at most once inside element <advice>", element);
  10. } else if (txAttributes.size() == 1) {
  11. // Using attributes source.
  12. Element attributeSourceElement = txAttributes.get(0);
  13. // 解析标签下属性,得到 NameMatchTransactionAttributeSource bean 定义
  14. RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext);
  15. builder.addPropertyValue("transactionAttributeSource", attributeSourceDefinition);
  16. } else {
  17. // Assume annotations source.
  18. builder.addPropertyValue("transactionAttributeSource",
  19. new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"));
  20. }
  21. }

parseAttributeSource |

这里解析的是
org.springframework.transaction.config.TxAdviceBeanDefinitionParser#parseAttributeSource

  1. private RootBeanDefinition parseAttributeSource(Element attrEle, ParserContext parserContext) {
  2. // 得到所有的 method 标签
  3. List<Element> methods = DomUtils.getChildElementsByTagName(attrEle, METHOD_ELEMENT);
  4. ManagedMap<TypedStringValue, RuleBasedTransactionAttribute> transactionAttributeMap =
  5. new ManagedMap<>(methods.size());
  6. transactionAttributeMap.setSource(parserContext.extractSource(attrEle));
  7. //
  8. for (Element methodEle : methods) {
  9. // 得到方法的名称
  10. String name = methodEle.getAttribute(METHOD_NAME_ATTRIBUTE);
  11. // 名称当做字符串处理
  12. TypedStringValue nameHolder = new TypedStringValue(name);
  13. nameHolder.setSource(parserContext.extractSource(methodEle));
  14. // 事务属性:设置方法的事务传播、隔离机制、超时、是否只读
  15. RuleBasedTransactionAttribute attribute = new RuleBasedTransactionAttribute();
  16. String propagation = methodEle.getAttribute(PROPAGATION_ATTRIBUTE);
  17. String isolation = methodEle.getAttribute(ISOLATION_ATTRIBUTE);
  18. String timeout = methodEle.getAttribute(TIMEOUT_ATTRIBUTE);
  19. String readOnly = methodEle.getAttribute(READ_ONLY_ATTRIBUTE);
  20. if (StringUtils.hasText(propagation)) {
  21. attribute.setPropagationBehaviorName(RuleBasedTransactionAttribute.PREFIX_PROPAGATION + propagation);
  22. }
  23. if (StringUtils.hasText(isolation)) {
  24. attribute.setIsolationLevelName(RuleBasedTransactionAttribute.PREFIX_ISOLATION + isolation);
  25. }
  26. if (StringUtils.hasText(timeout)) {
  27. try {
  28. attribute.setTimeout(Integer.parseInt(timeout));
  29. } catch (NumberFormatException ex) {
  30. parserContext.getReaderContext().error("Timeout must be an integer value: [" + timeout + "]", methodEle);
  31. }
  32. }
  33. if (StringUtils.hasText(readOnly)) {
  34. attribute.setReadOnly(Boolean.parseBoolean(methodEle.getAttribute(READ_ONLY_ATTRIBUTE)));
  35. }
  36. // 方法回滚的规则
  37. List<RollbackRuleAttribute> rollbackRules = new ArrayList<>(1);
  38. if (methodEle.hasAttribute(ROLLBACK_FOR_ATTRIBUTE)) {
  39. // 如果设置了rollback-for属性
  40. String rollbackForValue = methodEle.getAttribute(ROLLBACK_FOR_ATTRIBUTE);
  41. addRollbackRuleAttributesTo(rollbackRules, rollbackForValue);
  42. }
  43. if (methodEle.hasAttribute(NO_ROLLBACK_FOR_ATTRIBUTE)) {
  44. // 设置了no-rollback-for属性
  45. String noRollbackForValue = methodEle.getAttribute(NO_ROLLBACK_FOR_ATTRIBUTE);
  46. addNoRollbackRuleAttributesTo(rollbackRules, noRollbackForValue);
  47. }
  48. attribute.setRollbackRules(rollbackRules);
  49. transactionAttributeMap.put(nameHolder, attribute);
  50. }
  51. // 新建 NameMatchTransactionAttributeSource bean 定义
  52. RootBeanDefinition attributeSourceDefinition = new RootBeanDefinition(NameMatchTransactionAttributeSource.class);
  53. // 设置属性
  54. attributeSourceDefinition.setSource(parserContext.extractSource(attrEle));
  55. attributeSourceDefinition.getPropertyValues().add("nameMap", transactionAttributeMap);
  56. return attributeSourceDefinition;
  57. }

解析结果

最终的结果:
GenericBeanDefinition
beanClass:org.springframework.transaction.interceptor.TransactionInterceptor
Propertyvalues:
transactionManager
transactionAttributesource:
RootBeanDefinition
beanClass:org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource
Propertyvalues:
propertyvalueList:
nameMap:
[add] -> {RuleBasedTransactionAttribute@3649} “PROPAGATION_REQUIRED,ISOLATION_DEFAULT”
[delete] -> {RuleBasedTransactionAttribute@3651} “PROPAGATION_REQUIRED,ISOLATION_DEFAULT”
[update] -> {RuleBasedTransactionAttribute@3653} “PROPAGATION_REQUIRED,ISOLATION_DEFAULT”
[query]-> {RuleBasedTransactionAttribute@3655} “PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly”
可以看出将 tx:advice 标签解析成了 TransactionInterceptor 对象定义,通过属性嵌套了 NameMatchTransactionAttributeSource 对象定义

  1. <tx:advice id="interceptor" transaction-manager="transactionManager">
  2. <tx:attributes>
  3. <tx:method name="*add*" propagation="REQUIRED"/>
  4. <tx:method name="*delete*" propagation="REQUIRED"/>
  5. <tx:method name="*update*" propagation="REQUIRED"/>
  6. <tx:method name="*query*" read-only="true"/>
  7. </tx:attributes>
  8. </tx:advice>

再看下 RootBeanDefinition 、GenericBeanDefinition 父类关系。
image.png