<aop:config>标签解析

aop名称空间的解析器是AopNamespaceHandler

// 这里我们可以看到注册了几个解析器,重点关注ConfigBeanDefinitionParser

在ConfigBeanDefinitionParser的parse方法中对aop:config下面的三个直接子标签pointcut、advisor、aspect分别进行解析

// 注册AnnotationAwareAspectJAutoProxyCreator或AspectJAwareAdvisorAutoProxyCreatorconfigureAutoProxyCreator(parserContext, element);

List<Element> childElts = DomUtils.getChildElements(element);for (Element elt: childElts) {String localName = parserContext.getDelegate().getLocalName(elt);if (POINTCUT.equals(localName)) {parsePointcut(elt, parserContext);}else if (ADVISOR.equals(localName)) {parseAdvisor(elt, parserContext);}else if (ASPECT.equals(localName)) { parseAspect(elt, parserContext); } }

pointcut标签解析

private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {String id = pointcutElement.getAttribute(ID);String expression = pointcutElement.getAttribute(EXPRESSION);AbstractBeanDefinition pointcutDefinition = null;try {this.parseState.push(new PointcutEntry(id));       // 创建BeanDefinition,下边详解 pointcutDefinition = createPointcutDefinition(expression); pointcutDefinition.setSource(parserContext.extractSource(pointcutElement)); String pointcutBeanName = id; if (StringUtils.hasText(pointcutBeanName)) {         // 这里是注册bean parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition); } else { pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition); } parserContext.registerComponent( new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression)); } finally { this.parseState.pop(); } return pointcutDefinition; }

protected AbstractBeanDefinition createPointcutDefinition(String expression) {RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);beanDefinition.setSynthetic(true);beanDefinition.getPropertyValues().add(EXPRESSION, expression);return beanDefinition;}

我们可以看到RootBeanDefinition的beanClass是AspectJExpressionPointcut,也就是getBean时会实例化AspectJExpressionPointcut,并且为其设置了属性值expression如execution(* com.wjz.service.*.*(..))

我们来看一下AspectJExpressionPointcut的继承结构。这个类同时实现了ClassFilter和MethodMatcher接口执行类匹配和方法匹配逻辑。它有一个expression属性设置表达式,AspectJ最终会把该表达式解析成一个PointcutExpression对象执行相关的语义。后文详解

aspect标签解析

aspect标签的解析要相对复杂一些,解析它下面的所有通知子标签(aop:before、aop:after等标签)

       String aspectId = aspectElement.getAttribute(ID);String aspectName = aspectElement.getAttribute(REF);// 获得所有的通知子标签NodeList nodeList = aspectElement.getChildNodes();boolean adviceFoundAlready = false;for (int i = 0; i < nodeList.getLength(); i++) {Node node = nodeList.item(i);         // 判断是否是通知标签如before,after-returning if (isAdviceNode(node, parserContext)) { if (!adviceFoundAlready) { adviceFoundAlready = true; if (!StringUtils.hasText(aspectName)) { parserContext.getReaderContext().error( "<aspect> tag needs aspect bean reference via 'ref' attribute when declaring advices.", aspectElement, this.parseState.snapshot()); return; } beanReferences.add(new RuntimeBeanReference(aspectName)); }            // 解析并注册通知子标签,后文详解 AbstractBeanDefinition advisorDefinition = parseAdvice( aspectName, i, aspectElement, (Element) node, parserContext, beanDefinitions, beanReferences); beanDefinitions.add(advisorDefinition); } } AspectComponentDefinition aspectComponentDefinition = createAspectComponentDefinition( aspectElement, aspectId, beanDefinitions, beanReferences, parserContext); parserContext.pushContainingComponent(aspectComponentDefinition); List<Element> pointcuts = DomUtils.getChildElementsByTagName(aspectElement, POINTCUT); for (Element pointcutElement : pointcuts) { parsePointcut(pointcutElement, parserContext); } parserContext.popAndRegisterContainingComponent();

private AbstractBeanDefinition parseAdvice(String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext,List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {try {this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement)));// 通知标签的方法属性(method属性)会被解析成一个MethodLocatingFactoryBean类型的bean,并设置了methodName属性值       // 为AspectJMethodBeforeAdvice等的构造函数的形参作准备            RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class); methodDefinition.getPropertyValues().add("targetBeanName", aspectName); methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method")); methodDefinition.setSynthetic(true); // 创建AspectInstanceFactory的一个实例,为AspectJMethodBeforeAdvice等的构造函数的形参作准备
            RootBeanDefinition aspectFactoryDef = new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);aspectFactoryDef.setSynthetic(true);// 准备AspectJMethodBeforeAdvice等的构造函数,后文详解AbstractBeanDefinition adviceDef = createAdviceDefinition(adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,beanDefinitions, beanReferences);// 解析通知子标签为AspectJPointcutAdvisor对象RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);advisorDefinition.setSource(parserContext.extractSource(adviceElement));       // 设置AspectJPointcutAdvisor中的AbstractAspectJAdvice的构造函数参数信息advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);if (aspectElement.hasAttribute(ORDER_PROPERTY)) { advisorDefinition.getPropertyValues().add( ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY)); } // 注册通知子标签  parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition); return advisorDefinition; } finally { this.parseState.pop(); } }

private AbstractBeanDefinition createAdviceDefinition(Element adviceElement, ParserContext parserContext, String aspectName, int order,RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {// getAdviceClass()方法获得AspectJMethodBeforeAdvice、AspectJAfterReturningAdvice等RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));adviceDefinition.setSource(parserContext.extractSource(adviceElement));// 添加属性值adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);if (adviceElement.hasAttribute(RETURNING)) {adviceDefinition.getPropertyValues().add(RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));}if (adviceElement.hasAttribute(THROWING)) { adviceDefinition.getPropertyValues().add( THROWING_PROPERTY, adviceElement.getAttribute(THROWING)); } if (adviceElement.hasAttribute(ARG_NAMES)) { adviceDefinition.getPropertyValues().add( ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES)); }      // 准备AspectJMethodBeforeAdvice等构造函数所需的参数,为构造函数反射得到AspectJMethodBeforeAdvice做准备 ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues(); cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);      // 获得pointcut-ref属性值 Object pointcut = parsePointcutProperty(adviceElement, parserContext); if (pointcut instanceof BeanDefinition) { cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut); beanDefinitions.add((BeanDefinition) pointcut); } else if (pointcut instanceof String) { RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut); cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef); beanReferences.add(pointcutRef); } cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef); return adviceDefinition; }

AspectJMethodBeforeAdvice等的构造函数为

advisor标签解析

private void parseAdvisor(Element advisorElement, ParserContext parserContext) {     // 创建advisor标签对应的BeanDefinition,后文详解AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext);String id = advisorElement.getAttribute(ID);try {this.parseState.push(new AdvisorEntry(id));String advisorBeanName = id;       // 注册bean  if (StringUtils.hasText(advisorBeanName)) { parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef); } else { advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef); }        // 获得pointcut-ref属性值,添加属性 Object pointcut = parsePointcutProperty(advisorElement, parserContext); if (pointcut instanceof BeanDefinition) { advisorDef.getPropertyValues().add(POINTCUT, pointcut); parserContext.registerComponent( new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut)); } else if (pointcut instanceof String) { advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut)); parserContext.registerComponent( new AdvisorComponentDefinition(advisorBeanName, advisorDef)); } } finally { this.parseState.pop(); } }

private AbstractBeanDefinition createAdvisorBeanDefinition(Element advisorElement, ParserContext parserContext) {     // getBean时实例化一个DefaultBeanFactoryPointcutAdvisorRootBeanDefinition advisorDefinition = new RootBeanDefinition(DefaultBeanFactoryPointcutAdvisor.class);advisorDefinition.setSource(parserContext.extractSource(advisorElement));String adviceRef = advisorElement.getAttribute(ADVICE_REF);if (!StringUtils.hasText(adviceRef)) {parserContext.getReaderContext().error("'advice-ref' attribute contains empty value.", advisorElement, this.parseState.snapshot());}else { advisorDefinition.getPropertyValues().add( ADVICE_BEAN_NAME, new RuntimeBeanNameReference(adviceRef)); } if (advisorElement.hasAttribute(ORDER_PROPERTY)) { advisorDefinition.getPropertyValues().add( ORDER_PROPERTY, advisorElement.getAttribute(ORDER_PROPERTY)); } return advisorDefinition; }

转载于:https://www.cnblogs.com/BINGJJFLY/p/7452703.html

spring AOP解析之xml方式详解相关推荐

  1. 第14章-Spring AOP通知(Advice)详解

    文章目录 一.概述 二.通知的定义 1. 前置通知 2. 后置通知 3. 环绕通知 4. 最终通知 5. 异常通知 三.通知的参数 1. 切入点 2. 通知的参数传递 四.通知的顺序 五.附录 1. ...

  2. 【Spring AOP】@Aspect结合案例详解(二): @Pointcut使用@within和within(已附源码)

    文章目录 前言 @within 完善打印日志案例 @within深入说明 within 匹配指定类 匹配指定包(package) 源码下载 总结 前言 在微服务流行的当下,在使用Spring Clou ...

  3. java中四种操作(DOM、SAX、JDOM、DOM4J)xml方式详解与比较(转)

    java中四种操作(DOM.SAX.JDOM.DOM4J)xml方式详解与比较(转) http://wishlife.javaeye.com/blog/181865 posted on 2010-12 ...

  4. Spring源码深度解析(五):Spring AOP原理及源码详解

    前言 OOP表示面向对象编程,是一种编程思想:AOP表示面向切面编程,也是一种编程思想,AOP的概念可以参考文章:SpringAOP基本概念详解. 正文 1.AbstractAdvisorAutoPr ...

  5. Spring AOP 增强框架 Nepxion Matrix 详解

    点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 概述 在<深入聊一聊 Spring AOP 实现机制>一文中,介绍了 Spring A ...

  6. spring aop实例讲解_Spring核心技术详解(一)

    一.Sring简介 Spring是一个分层的Java SE/EE应用一站式的轻量级开源框架.Spring核心是IOC和AOP. Spring主要优点包括: 方便解耦,简化开发,通过Spring提供的I ...

  7. Spring 是解析配置类过程详解

    Spring执行流程图如下: Spring执行流程图 这个流程图会随着我们的学习不断的变得越来越详细,也会越来越复杂,希望在这个过程中我们都能朝着精通Spring的目标不断前进!  在上篇文章我们学 ...

  8. Spring AOP中定义切点PointCut详解

    1.AOP是什么? 软件工程有一个基本原则叫做"关注点分离"(Concern Separation),通俗的理解就是不同的问题交给不同的部分去解决,每部分专注于解决自己的问题.这年 ...

  9. 14.spring aop之aspect切入点语法详解

    1.Spring AOP支持的AspectJ切入点指示符 切入点指示符用来指示切入点表达式目的,,在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的AspectJ切入点指 ...

最新文章

  1. java观察者模式类图_设计模式(十八)——观察者模式(JDK Observable源码分析)...
  2. Python 进阶_闭包 装饰器
  3. python内存管理说法错误_python面试题总结1-内存管理机制
  4. MongoDB分布式操作——分片操作
  5. python人工智能pdf_800G人工智能学习资料:AI电子书+Python语言入门+教程+机器学习等限时免费领取!...
  6. urtracker 项目管理工具
  7. 长痘痘了吃什么好得快?
  8. TP5的安装部署概要
  9. Mac 下 CocoaPods软件⁩汉化
  10. 我看过的关于职业规划最好最全面的一篇文章
  11. 小程序数据分析工具:TalkingData
  12. IOCTL 获取网络信息(Ethtool工具)
  13. 利用freemarker导出Excel(格式自定义)
  14. 软件外包项目这样做,快速拿下一个个项目金!
  15. 计算机毕业设计Android宠物领养救助系统app(源码+系统+mysql数据库+Lw文档)
  16. 工信部怒了,App 厂商们又作死
  17. DCM4CHE处理多帧图像
  18. 直观理解拉格朗日乘子法和Karush-Kuhn-Tucker(KKT)条件
  19. CDH大数据平台 Error while compiling statement: FAILED: SemanticException No valid privileges User tianlin
  20. 英寸和厘米的换算python_Python的新手-尝试将厘米编码为英寸,反之亦...

热门文章

  1. 如何提高一个研发团队的“代码速度”?
  2. 如何用智能有效感知城市?城市大脑三大AI产品来了
  3. Galgame研发日志:那么,怎么才能回本呢?
  4. CSDN创始人蒋涛:开源吞噬世界,得开发者得天下
  5. js_jQuery【下拉菜单联动dom操作】
  6. 黑客技术的网站(❤️可以自学,建议收藏❤️)
  7. 学会这个用这个做PPT,把24小时的工作变成1秒!高效神器保住你的发际线~
  8. Linux 添加DNS配置
  9. antd 刷新页面及后退时菜单栏高亮问题
  10. 【bzoj2226】[Spoj 5971] LCMSum 欧拉函数