Spring 事务源码(二):beanDefinition的准备-配置文件加载
一、BeanDefinition预览
![](https://img2023.cnblogs.com/blog/1680081/202212/1680081-20221231195334436-62804679.png)
Spring中的事务是基于AOP实现的,在实现AOP中有几个核心的对象:AspectJAwareAdvisorAutoProxyCreator、Advisor、PointCut、MethodInterceptor。在开始正式分析源码前,根据上述的beanDefinition集合容器与AOP的核心对象,可发现如下映射关系
AspectJAwareAdvisorAutoProxyCreator在AOP源码分析中已做介绍,不再赘述,下面来看看Spring事务中Advisor、Advice、Pointcut的beanDefinition加载工作。
二、BeanDefinition的加载
![](https://img2023.cnblogs.com/blog/1680081/202212/1680081-20221231195518973-1578149123.png)
2.1、PropertySourcesPlaceholderConfigurer 主要用于占位符解析
类图关系中,PropertySourcesPlaceholderConfigurer属于BeanFactoryPostProcessor,在IOC容器刷新时,在invokeBeanFactoryPostProcessors(beanFactory)方法中处理该BeanDefinition的实例化、初始化过程。
2.2、AspectJExpressionPointcut 切点
1、AspectJExpressionPointcut切点解析的核心流程图
2、AspectJExpressionPointcut切点解析的核心代码
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 }
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 }