spring AOP解析之xml方式详解
<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方式详解相关推荐
- 第14章-Spring AOP通知(Advice)详解
文章目录 一.概述 二.通知的定义 1. 前置通知 2. 后置通知 3. 环绕通知 4. 最终通知 5. 异常通知 三.通知的参数 1. 切入点 2. 通知的参数传递 四.通知的顺序 五.附录 1. ...
- 【Spring AOP】@Aspect结合案例详解(二): @Pointcut使用@within和within(已附源码)
文章目录 前言 @within 完善打印日志案例 @within深入说明 within 匹配指定类 匹配指定包(package) 源码下载 总结 前言 在微服务流行的当下,在使用Spring Clou ...
- java中四种操作(DOM、SAX、JDOM、DOM4J)xml方式详解与比较(转)
java中四种操作(DOM.SAX.JDOM.DOM4J)xml方式详解与比较(转) http://wishlife.javaeye.com/blog/181865 posted on 2010-12 ...
- Spring源码深度解析(五):Spring AOP原理及源码详解
前言 OOP表示面向对象编程,是一种编程思想:AOP表示面向切面编程,也是一种编程思想,AOP的概念可以参考文章:SpringAOP基本概念详解. 正文 1.AbstractAdvisorAutoPr ...
- Spring AOP 增强框架 Nepxion Matrix 详解
点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 概述 在<深入聊一聊 Spring AOP 实现机制>一文中,介绍了 Spring A ...
- spring aop实例讲解_Spring核心技术详解(一)
一.Sring简介 Spring是一个分层的Java SE/EE应用一站式的轻量级开源框架.Spring核心是IOC和AOP. Spring主要优点包括: 方便解耦,简化开发,通过Spring提供的I ...
- Spring 是解析配置类过程详解
Spring执行流程图如下: Spring执行流程图 这个流程图会随着我们的学习不断的变得越来越详细,也会越来越复杂,希望在这个过程中我们都能朝着精通Spring的目标不断前进! 在上篇文章我们学 ...
- Spring AOP中定义切点PointCut详解
1.AOP是什么? 软件工程有一个基本原则叫做"关注点分离"(Concern Separation),通俗的理解就是不同的问题交给不同的部分去解决,每部分专注于解决自己的问题.这年 ...
- 14.spring aop之aspect切入点语法详解
1.Spring AOP支持的AspectJ切入点指示符 切入点指示符用来指示切入点表达式目的,,在Spring AOP中目前只有执行方法这一个连接点,Spring AOP支持的AspectJ切入点指 ...
最新文章
- java观察者模式类图_设计模式(十八)——观察者模式(JDK Observable源码分析)...
- Python 进阶_闭包 装饰器
- python内存管理说法错误_python面试题总结1-内存管理机制
- MongoDB分布式操作——分片操作
- python人工智能pdf_800G人工智能学习资料:AI电子书+Python语言入门+教程+机器学习等限时免费领取!...
- urtracker 项目管理工具
- 长痘痘了吃什么好得快?
- TP5的安装部署概要
- Mac 下 CocoaPods软件汉化
- 我看过的关于职业规划最好最全面的一篇文章
- 小程序数据分析工具:TalkingData
- IOCTL 获取网络信息(Ethtool工具)
- 利用freemarker导出Excel(格式自定义)
- 软件外包项目这样做,快速拿下一个个项目金!
- 计算机毕业设计Android宠物领养救助系统app(源码+系统+mysql数据库+Lw文档)
- 工信部怒了,App 厂商们又作死
- DCM4CHE处理多帧图像
- 直观理解拉格朗日乘子法和Karush-Kuhn-Tucker(KKT)条件
- CDH大数据平台 Error while compiling statement: FAILED: SemanticException No valid privileges User tianlin
- 英寸和厘米的换算python_Python的新手-尝试将厘米编码为英寸,反之亦...