死磕Spring之AOP篇 - Spring AOP注解驱动与XML配置 (6)

解析 <aop:config /> 标签,注册 AspectJAwareAdvisorAutoProxyCreator 自动代理对象(如果需要的话),设置为优先级最高

private void configureAutoProxyCreator(ParserContext parserContext, Element element) { // 注册 AspectJAwareAdvisorAutoProxyCreator 自动代理对象(如果需要的话) AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element); }

过程和 @EnableAspectJAutoProxy、<aop:aspectj-autoproxy /> 的解析过程差不多,这里不再进行展述

获取 <aop:config /> 的子标签,遍历进行处理

调用 parsePointcut(..) 方法,处理 <aop:pointcut /> 子标签,解析出 AspectJExpressionPointcut 对象并注册

调用 parseAdvisor(..) 方法,处理 <aop:advisor /> 子标签,解析出 DefaultBeanFactoryPointcutAdvisor 对象并注册,了指定 Advice 和 Pointcut(如果有)

调用 parseAspect(..) 方法,处理 <aop:aspectj /> 子标签,解析出所有的 AspectJPointcutAdvisor 对象并注册,里面包含了 Advice 对象和对应的 Pointcut 对象;同时存在 Pointcut 配置,也会解析出 AspectJExpressionPointcut 对象并注册

我们依次来看看你上面三种子标签的处理过程

<aop:pointcut /> <beans> <aop:aspectj-autoproxy/> <bean/> <aop:config> <aop:pointcut expression="execution(public String *(..))"/> </aop:config> </beans>

处理过程在 parsePointcut(..) 方法中,如下:

// ConfigBeanDefinitionParser.java private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) { // <1> 获取 <aop:pointcut /> 标签的 `id` 和 `expression` 配置 String id = pointcutElement.getAttribute(ID); String expression = pointcutElement.getAttribute(EXPRESSION); AbstractBeanDefinition pointcutDefinition = null; try { this.parseState.push(new PointcutEntry(id)); // <2> 创建一个 AspectJExpressionPointcut 类型的 RootBeanDefinition 对象 pointcutDefinition = createPointcutDefinition(expression); // <3> 设置来源 pointcutDefinition.setSource(parserContext.extractSource(pointcutElement)); String pointcutBeanName = id; // <4> 注册这个 AspectJExpressionPointcut 对象 if (StringUtils.hasText(pointcutBeanName)) { // <4.1> 如果 `id` 配置不为空,则取其作为名称 parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition); } else { // <4.2> 否则,自动生成名称,也就是取 `className` pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition); } // <5> 将注册的 BeanDefinition 包装成 ComponentDefinition 放入 `parserContext` 上下文中,暂时忽略 parserContext.registerComponent( new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression)); } finally { this.parseState.pop(); } return pointcutDefinition; }

解析过程大致如下:

获取 <aop:pointcut /> 标签的 id 和 expression 配置

根据 expression 表达式创建一个 AspectJExpressionPointcut 类型的 RootBeanDefinition 对象,如下:

protected AbstractBeanDefinition createPointcutDefinition(String expression) { // <1> 创建一个 AspectJExpressionPointcut 类型的 RootBeanDefinition 对象 RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class); // <2> 设置为原型模式,需要保证每次获取到的 Pointcut 对象都是新的,防止在某些地方被修改而影响到其他地方 beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE); // <3> 设置为是 Spring 内部合成的 beanDefinition.setSynthetic(true); // <4> 添加 `expression` 属性值 beanDefinition.getPropertyValues().add(EXPRESSION, expression); // <5> 返回刚创建的 RootBeanDefinition 对象 return beanDefinition; }

设置来源

注册这个 AspectJExpressionPointcut 对象

如果 id 配置不为空,则取其作为名称

否则,自动生成名称,也就是取 className

将注册的 BeanDefinition 包装成 ComponentDefinition 放入 parserContext 上下文中,暂时忽略

<aop:advisor /> <beans> <aop:aspectj-autoproxy/> <bean/> <aop:config> <aop:pointcut expression="execution(public String *(..))"/> <aop:advisor advice-ref="echoServiceMethodInterceptor" pointcut-ref="anyPublicStringMethod" /> </aop:config> </beans>

处理过程在 parseAdvisor(..) 方法中,如下:

// ConfigBeanDefinitionParser.java private void parseAdvisor(Element advisorElement, ParserContext parserContext) { // <1> 解析 <aop:advisor /> 标签 // 创建一个 DefaultBeanFactoryPointcutAdvisor 类型的 RootBeanDefinition 对象,并指定了 Advice AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext); // <2> 获取 `id` 属性 String id = advisorElement.getAttribute(ID); try { this.parseState.push(new AdvisorEntry(id)); String advisorBeanName = id; // <3> 注册第 `1` 步创建的 RootBeanDefinition if (StringUtils.hasText(advisorBeanName)) { // <3.1> 如果 `id` 不为空,则取其作为名称 parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef); } else { // <3.2> 否则,生成一个名称,也就是 `className` advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef); } // <4> 获取这个 Advisor 对应的 Pointcut(也许就是一个 AspectJExpressionPointcut,也可能是引用的 Pointcut 的名称) Object pointcut = parsePointcutProperty(advisorElement, parserContext); // <4.1> 如果是 AspectJExpressionPointcut if (pointcut instanceof BeanDefinition) { // 第 `1` 步创建的 RootBeanDefinition 添加 `pointcut` 属性,指向这个 AspectJExpressionPointcut advisorDef.getPropertyValues().add(POINTCUT, pointcut); parserContext.registerComponent( new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut)); } // <4.2> 否则,如果是一个引用的 Pointcut 的名称 else if (pointcut instanceof String) { // 第 `1` 步创建的 RootBeanDefinition 添加 `pointcut` 属性,指向这个名称对应的引用 advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut)); parserContext.registerComponent( new AdvisorComponentDefinition(advisorBeanName, advisorDef)); } } finally { this.parseState.pop(); } }

解析过程大致如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygssw.html