Spring 事务源码(二):beanDefinition的准备-配置文件加载

  
  普通bean标签的beanDefinition的解析不再赘述,仅对事务相关的核心beanDefinition的获取做分析。

一、BeanDefinition预览

  IOC容器刷新完成后,容器中的BeanDefinition详情如下:
 

  Spring中的事务是基于AOP实现的,在实现AOP中有几个核心的对象:AspectJAwareAdvisorAutoProxyCreator、Advisor、PointCut、MethodInterceptor。在开始正式分析源码前,根据上述的beanDefinition集合容器与AOP的核心对象,可发现如下映射关系

  AspectJAwareAdvisorAutoProxyCreator在AOP源码分析中已做介绍,不再赘述,下面来看看Spring事务中Advisor、Advice、Pointcut的beanDefinition加载工作。

二、BeanDefinition的加载

  Spring解析自定义标签的通用流程:

2.1、PropertySourcesPlaceholderConfigurer 主要用于占位符解析

  类图关系中,PropertySourcesPlaceholderConfigurer属于BeanFactoryPostProcessor,在IOC容器刷新时,在invokeBeanFactoryPostProcessors(beanFactory)方法中处理该BeanDefinition的实例化、初始化过程。

  1、根据元素节点的命令空间,在指定模块的spring.handlers中,找到命名空间与对应beanDefinition的解析处理类ContextNamespaceHandler;
  2、通过ContextNamespaceHandler获取元素beanDefinition解析器PropertyPlaceholderBeanDefinitionParser;
  3、在解析器中通过BeanDefinitionBuilder创建beanDefinition并对beanDefinition做赋值操作。

2.2、AspectJExpressionPointcut 切点

1、AspectJExpressionPointcut切点解析的核心流程图

2、AspectJExpressionPointcut切点解析的核心代码

  ConfigBeanDefinitionParser#parse 核心伪代码
 1 // 切点解析核心伪代码
 2 public BeanDefinition parse(Element element, ParserContext parserContext) {
 3 
 4    // 注册自动代理模式创建器,AspectjAwareAdvisorAutoProxyCreator
 5    configureAutoProxyCreator(parserContext, element);
 6    
 7    // 解析aop:config子节点下的aop:pointcut/aop:advisor/aop:aspect等标签元素
 8    List<Element> childElts = DomUtils.getChildElements(element);
 9    
10    // 遍历子元素
11    for (Element elt: childElts) {
12       // 获取标签名称
13       String localName = parserContext.getDelegate().getLocalName(elt);
14       // pointcut的解析
15       if (POINTCUT.equals(localName)) {
16          parsePointcut(elt, parserContext);
17       }
18    }
19    return null;
20 }

  ConfigBeanDefinitionParser#parsePointcut 核心伪代码:

1 // 解析切入点
2 private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {
3    // 获取切入点的表达式
4    String expression = pointcutElement.getAttribute(EXPRESSION);
5    // 创建pointcut的beanDefinition
6    AbstractBeanDefinition  pointcutDefinition = createPointcutDefinition(expression);
7    // 返回bean定义信息
8    return pointcutDefinition;
9 }

  ConfigBeanDefinitionParser#createPointcutDefinition 核心代码

 1 // 创建pointcut的beanDefinition并返回
 2 protected AbstractBeanDefinition createPointcutDefinition(String expression) {
 3    // 为AspectJExpressionPointcut创建bean定义信息
 4    RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
 5    // 设置bean定义信息为原型模式
 6    beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
 7    // 代理标识设置为true
 8    beanDefinition.setSynthetic(true);
 9    // 将切点表达式设置进bean定义信息中
10    beanDefinition.getPropertyValues().add(EXPRESSION, expression);
11    return beanDefinition;
12 }

2.3、DefaultBeanFactoryPointcutAdvisor 的beanDefinition加载

1、DefaultBeanFactoryPointcutAdvisor 的beanDefinition加载核心流程

2、DefaultBeanFactoryPointcutAdvisor 的beanDefinition加载核心伪代码

  ConfigBeanDefinitionParser#parseAdvisor 解析Advisor标签获取beanDefinition

 1 // 解析Advisor标签
 2 private void parseAdvisor(Element advisorElement, ParserContext parserContext) {
 3    // 解析<aop:advisor>节点,最终创建的beanClass为`DefaultBeanFactoryPointcutAdvisor`
 4    AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext);
 5    
 6    // 生成Advisor的beanName并注册至beanDefinitionMap
 7    String advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef);
 8 
 9    // 解析point-cut属性并赋值到DefaultBeanFactoryPointcutAdvisor#pointcut内部属性
10    Object pointcut = parsePointcutProperty(advisorElement, parserContext);
11    // 将pointcut设置Advisor的beanDefinition的propertyValues属性中
12    advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut));
13 }

  ConfigBeanDefinitionParser#createAdvisorBeanDefinition 创建Advisor的beanDefinition

 1 // 创建Advisor的beanDefinition
 2 private AbstractBeanDefinition createAdvisorBeanDefinition(Element advisorElement, ParserContext parserContext) {
 3    // 创建DefaultBeanFactoryPointcutAdvisor的beanDefinition
 4    RootBeanDefinition advisorDefinition = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class);
 5    
 6    // 获取advice-ref属性
 7    String adviceRef = advisorElement.getAttribute(ADVICE_REF);
 8    // 将advice-red属性值设置进beanDefinition的propertyValues属性中
 9    advisorDefinition.getPropertyValues().add(ADVICE_BEAN_NAME, new RuntimeBeanNameReference(adviceRef));
10    
11    // 返回beanDefinition
12    return advisorDefinition;
13 }

2.4、TransactionInterceptor Advice

1、TransactionInterceptor 解析Advice标签获取beanDefinition 核心流程图

2、TransactionInterceptor 解析Advice标签获取beanDefinition 核心伪代码

  TxAdviceBeanDefinitionParser#parseInternal 解析advice标签获取beanDefinition

 1 protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
 2    // 创建beanDefinition
 3    BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
 4    // 获取TransactionInterceptor的Class对象
 5    Class<?> beanClass = getBeanClass(element);
 6    // 为beanDefinition设置beanClass
 7    builder.getRawBeanDefinition().setBeanClass(beanClass);
 8    // 
 9    // 解析method,获取事务传播特性、隔离级别等事务信息,将事务信息封装至NameMatchTransactionAttributeSource对象,
10    // 并将NameMatchTransactionAttributeSource设置在advice的beanDefinition中
11    doParse(element, parserContext, builder);
12    return builder.getBeanDefinition();
13 }

  TxAdviceBeanDefinitionParser#doParse 解析attributes标签获取beanDefinition填充值Advice的beanDefinition中

1 protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
2   // 获取attributes标签元素信息
3   Element attributeSourceElement = txAttributes.get(0);
4   // 解析attributes标签元素信息
5   RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext);
6   // 将解析后attributes标签元素信息填充值Advice的beanDefinition中
7   builder.addPropertyValue("transactionAttributeSource", attributeSourceDefinition);
8 }
  TxAdviceBeanDefinitionParser#parseAttributeSourcee 解析method标签设置事务信息并用NameMatchTransactionAttributeSource封装事务信息
 1 // 解析attribute标签元素信息
 2 private RootBeanDefinition parseAttributeSource(Element attrEle, ParserContext parserContext) {
 3    // 获取attributes下的所有methods元素
 4    List<Element> methods = DomUtils.getChildElementsByTagName(attrEle, METHOD_ELEMENT);
 5    // 创建事务属性信息容器
 6    ManagedMap<TypedStringValue, RuleBasedTransactionAttribute> transactionAttributeMap =
 7          new ManagedMap<>(methods.size());
 8    
 9    // 遍历所有method元素,将method的事务属性信息添加进transactionAttributeMap容器
10    for (Element methodEle : methods) {
11       // 获取方法的名称
12       String name = methodEle.getAttribute(METHOD_NAME_ATTRIBUTE);
13       // 用TypedStringValue对象封装方法名称
14       TypedStringValue nameHolder = new TypedStringValue(name);
15 
16       // 事务信息获取并设置
17       RuleBasedTransactionAttribute attribute = new RuleBasedTransactionAttribute();
18       // 传播特性
19       String propagation = methodEle.getAttribute(PROPAGATION_ATTRIBUTE);
20       // 隔离级别
21       String isolation = methodEle.getAttribute(ISOLATION_ATTRIBUTE);
22       // 超时时间
23       String timeout = methodEle.getAttribute(TIMEOUT_ATTRIBUTE);
24       // 是否为只读事务
25       String readOnly = methodEle.getAttribute(READ_ONLY_ATTRIBUTE);
26       if (StringUtils.hasText(propagation)) {
27          attribute.setPropagationBehaviorName(RuleBasedTransactionAttribute.PREFIX_PROPAGATION + propagation);
28       }
29       if (StringUtils.hasText(isolation)) {
30          attribute.setIsolationLevelName(RuleBasedTransactionAttribute.PREFIX_ISOLATION + isolation);
31       }
32       if (StringUtils.hasText(timeout)) {
33          try {
34             attribute.setTimeout(Integer.parseInt(timeout));
35          }
36          catch (NumberFormatException ex) {
37             parserContext.getReaderContext().error("Timeout must be an integer value: [" + timeout + "]", methodEle);
38          }
39       }
40       if (StringUtils.hasText(readOnly)) {
41          attribute.setReadOnly(Boolean.parseBoolean(methodEle.getAttribute(READ_ONLY_ATTRIBUTE)));
42       }
43       
44       // 设置rollback规则
45       List<RollbackRuleAttribute> rollbackRules = new ArrayList<>(1);
46       if (methodEle.hasAttribute(ROLLBACK_FOR_ATTRIBUTE)) {
47          String rollbackForValue = methodEle.getAttribute(ROLLBACK_FOR_ATTRIBUTE);
48          addRollbackRuleAttributesTo(rollbackRules, rollbackForValue);
49       }
50       // 设置norollback规则 
51       if (methodEle.hasAttribute(NO_ROLLBACK_FOR_ATTRIBUTE)) {
52          String noRollbackForValue = methodEle.getAttribute(NO_ROLLBACK_FOR_ATTRIBUTE);
53          addNoRollbackRuleAttributesTo(rollbackRules, noRollbackForValue);
54       }
55       attribute.setRollbackRules(rollbackRules);
56       
57       // 将方法的事务属性信息添加进transactionAttributeMap事务属性容器
58       transactionAttributeMap.put(nameHolder, attribute);
59    }
60    
61    // 创建NameMatchTransactionAttributeSource的beanDefinition信息
62    RootBeanDefinition attributeSourceDefinition = new RootBeanDefinition(NameMatchTransactionAttributeSource.class);
63    // 将方法事务属性容器设置进NameMatchTransactionAttributeSource的beanDefinition中的propertyValues属性
64    attributeSourceDefinition.getPropertyValues().add("nameMap", transactionAttributeMap);
65    // 返回带有方法事务属性信息的beanDefinition
66    return attributeSourceDefinition;
67 }

 

posted @ 2022-12-31 20:06  无虑的小猪  阅读(98)  评论(0编辑  收藏  举报