springAOP入口之AopNamespaceHandler.doc_第1页
springAOP入口之AopNamespaceHandler.doc_第2页
springAOP入口之AopNamespaceHandler.doc_第3页
springAOP入口之AopNamespaceHandler.doc_第4页
springAOP入口之AopNamespaceHandler.doc_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

springAOP入口之AopNamespaceHandler我们从spring.handlers入口开始看:/schema/aop=org.springframework.aop.config.AopNamespaceHandler1打开类AopNamespaceHandler,代码如下:package org.springframework.aop.config;import org.springframework.aop.aspectj.AspectJExpressionPointcut;import org.springframework.beans.factory.xml.BeanDefinitionParser;import org.springframework.beans.factory.xml.NamespaceHandlerSupport;/* * code NamespaceHandler for the code aop namespace. * * Provides a link org.springframework.beans.factory.xml.BeanDefinitionParser for the * code <aop:config> tag. A code config tag can include nested * code pointcut, code advisor and code aspect tags. * * The code pointcut tag allows for creation of named * link AspectJExpressionPointcut beans using a simple syntax: * * <aop:pointcut id="getNameCalls" expression="execution(* *.ITestBean.getName(.)"/> * * * Using the code advisor tag you can configure an link org.springframework.aop.Advisor * and have it applied to all relevant beans in you link org.springframework.beans.factory.BeanFactory * automatically. The code advisor tag supports both in-line and referenced * link org.springframework.aop.Pointcut Pointcuts: * * * <aop:advisor id="getAgeAdvisor" * pointcut="execution(* *.ITestBean.getAge(.)" * advice-ref="getAgeCounter"/> * * <aop:advisor id="getNameAdvisor" * pointcut-ref="getNameCalls" * advice-ref="getNameCounter"/> * * author Rob Harrop * author Adrian Colyer * author Juergen Hoeller * since 2.0 */public class AopNamespaceHandler extends NamespaceHandlerSupport /* * Register the link BeanDefinitionParser BeanDefinitionParsers for the * code config, code spring-configured, code aspectj-autoproxy * and code scoped-proxy tags. */ Override public void init() / In 2.0 XSD as well as in 2.1 XSD. registerBeanDefinitionParser(config, new ConfigBeanDefinitionParser(); registerBeanDefinitionParser(aspectj-autoproxy, new AspectJAutoProxyBeanDefinitionParser(); registerBeanDefinitionDecorator(scoped-proxy, new ScopedProxyBeanDefinitionDecorator(); / Only in 2.0 XSD: moved to context namespace as of 2.1 registerBeanDefinitionParser(spring-configured, new SpringConfiguredBeanDefinitionParser(); 根据注释,该类是aop命名空间的处理类。 利用BeanDefinitionParser解析aop:config标签,该标签包括pointcut、advisor、aspect标签。 pointcut标签允许创建AspectJExpressionPointcut,利用简单的语法: 1使用advisor标签能够配置org.springframework.aop.Advisor,并且能自动应用的bean对象中。 advisor标签支持内联定义的或者引用的org.springframework.aop.Pointcut Pointcuts: 再看AopNamespaceHandler的类结构图: image接口NamespaceHandler先上源码:package org.springframework.beans.factory.xml;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.springframework.beans.factory.config.BeanDefinition;import org.springframework.beans.factory.config.BeanDefinitionHolder;/* * Base interface used by the link DefaultBeanDefinitionDocumentReader * for handling custom namespaces in a Spring XML configuration file. * * Implementations are expected to return implementations of the * link BeanDefinitionParser interface for custom top-level tags and * implementations of the link BeanDefinitionDecorator interface for * custom nested tags. * * The parser will call link #parse when it encounters a custom tag * directly under the code <beans> tags and link #decorate when * it encounters a custom tag directly under a code <bean> tag. * * Developers writing their own custom element extensions typically will * not implement this interface directly, but rather make use of the provided * link NamespaceHandlerSupport class. * * author Rob Harrop * author Erik Wiersma * since 2.0 * see DefaultBeanDefinitionDocumentReader * see NamespaceHandlerResolver */public interface NamespaceHandler /* * Invoked by the link DefaultBeanDefinitionDocumentReader after * construction but before any custom elements are parsed. * see NamespaceHandlerSupport#registerBeanDefinitionParser(String, BeanDefinitionParser) */ void init(); /* * Parse the specified link Element and register any resulting * link BeanDefinition BeanDefinitions with the * link org.springframework.beans.factory.support.BeanDefinitionRegistry * that is embedded in the supplied link ParserContext. * Implementations should return the primary code BeanDefinition * that results from the parse phase if they wish to be used nested * inside (for example) a code <property> tag. * Implementations may return code null if they will * not be used in a nested scenario. * param element the element that is to be parsed into one or more code BeanDefinitions * param parserContext the object encapsulating the current state of the parsing process * return the primary code BeanDefinition (can be code null as explained above) */ BeanDefinition parse(Element element, ParserContext parserContext); /* * Parse the specified link Node and decorate the supplied * link BeanDefinitionHolder, returning the decorated definition. * The link Node may be either an link org.w3c.dom.Attr or an * link Element, depending on whether a custom attribute or element * is being parsed. * Implementations may choose to return a completely new definition, * which will replace the original definition in the resulting * link org.springframework.beans.factory.BeanFactory. * The supplied link ParserContext can be used to register any * additional beans needed to support the main definition. * param source the source element or attribute that is to be parsed * param definition the current bean definition * param parserContext the object encapsulating the current state of the parsing process * return the decorated definition (to be registered in the BeanFactory), * or simply the original bean definition if no decoration is required. * A code null value is strictly speaking invalid, but will be leniently * treated like the case where the original bean definition gets returned. */ BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);该接口是供处理spring的xml配置文件类DefaultBeanDefinitionDocumentReader使用的基接口。 实现类需要返回顶级标签和BeanDefinitionDecorator定义的内嵌标签的实现。 该解析器在遇到自定义的bean标签时会调用parse()和decorate()方法.抽象类NamespaceHandlerSupport源码如下:package org.springframework.beans.factory.xml;import java.util.HashMap;import java.util.Map;import org.w3c.dom.Attr;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.springframework.beans.factory.config.BeanDefinition;import org.springframework.beans.factory.config.BeanDefinitionHolder;/* * 实现了NamespaceHandlers的支持类,通过BeanDefinitionParser和BeanDefinitionDecorator的策略接口解析和装饰 * 提供了相应的方法注册解析器去处理具体的元素 */public abstract class NamespaceHandlerSupport implements NamespaceHandler /* * 保存BeanDefinitionParser的实现 */ private final Map parsers = new HashMap(); /* * 保存BeanDefinitionDecorator的实现 */ private final Map decorators = new HashMap(); /* * 根据属性保存BeanDefinitionDecorator的实现 */ private final Map attributeDecorators = new HashMap(); /* * 解析Element元素并注册 */ Override public BeanDefinition parse(Element element, ParserContext parserContext) return findParserForElement(element, parserContext).parse(element, parserContext); /* * 根据Element查找注册的BeanDefinitionParser */ private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) String localName = parserContext.getDelegate().getLocalName(element); BeanDefinitionParser parser = sers.get(localName); if (parser = null) parserContext.getReaderContext().fatal( Cannot locate BeanDefinitionParser for element + localName + , element); return parser; /* * 装饰代理的BeanDefinitionDecorator,被注册用来处理Node */ Override public BeanDefinitionHolder decorate( Node node, BeanDefinitionHolder definition, ParserContext parserContext) return findDecoratorForNode(node, parserContext).decorate(node, definition, parserContext); /* * 从注册的实现类找出BeanDefinitionParser,支持Element(s)和Attr(s) */ private BeanDefinitionDecorator findDecoratorForNode(Node node, ParserContext parserContext) BeanDefinitionDecorator decorator = null; String localName = parserContext.getDelegate().getLocalName(node); if (node instanceof Element) decorator = this.decorators.get(localName); else if (node instanceof Attr) decorator = this.attributeDecorators.get(localName); else parserContext.getReaderContext().fatal( Cannot decorate based on Nodes of type + node.getClass().getName() + , node); if (decorator = null) parserContext.getReaderContext().fatal(Cannot locate BeanDefinitionDecorator for + (node instanceof Element ? element : attribute) + + localName + , node); return decorator; /* * 子类调用注册BeanDefinitionParser来处理具体的元素 */ protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) this.parsers.put(elementName, parser); /* * 子类调用注册BeanDefinitionDecorator来处理具体的元素 */ protected final void registerBeanDefinitionDecorator(String elementName, BeanDefinitionDecorator dec) this.decorators.put(elementName, dec); /* * 子类调用注册BeanDefinitionDecorator处理具体的属性 */ protected final void registerBeanDefinitionDecoratorForAttribute(String attrName, BeanDefinitionDecorator dec) this.attributeDecorators.put(attrName, dec); AopNamespaceHandler.init()回看AopNamespaceHandler.init()的方法体: 先从解析config元素开始:registerBeanDefinitionParser(config, new ConfigBeanDefinitionParser();1注册BeanDefinitionParser解析器,会自动调用该解析器(ConfigBeanDefinitionParser)的parse方法: /利用内嵌在ParserContext里的BeanDefinition进行注册并解析具体的元素 Override public BeanDefinition parse(Element element, ParserContext parserContext) /从parserContext里获取复合的组件定义 CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element); parserContext.pushContainingComponent(compositeDef); /自动代理创建者所需的配置,用于支持通过标签创建的BeanDefinitions /当proxy-target-class=true,将强制进行类的代理 configureAutoProxyCreator(parserContext, element); List childElts = DomUtils.getChildElements(element); for (Element elt: childElts) String localName = parserContext.getDelegate().getLocalName(elt); if (POINTCUT.equals(localName) /解析提供的pointcut并利用BeanDefinitionRegistry注册 parsePointcut(elt, parserContext); else if (ADVISOR.equals(localName) parseAdvisor(elt, parserContext); else if (ASPECT.equals(localName) parseAspect(elt, parserContext); parserContext.popAndRegisterContainingComponent(); return null; 接下来我们看看parsePointcut完成了哪些事情: /* * Parses the supplied code <pointcut> and registers the resulting * Pointcut with the BeanDefinitionRegistry. */ 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); /AspectJExpressionPointcut使用给定的表达式创建BeanDefinition pointcutDefinition = createPointcutDefinition(expression); pointcutDefinition.setSource(parserContext.extractSource(pointcutElement); String pointcutBeanName = id; /进行注册,切点名称为空时,自动生成 if (StringUtils.hasText(pointcutBeanName) parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition); else pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition); /注册切点组件 parserContext.registerComponent( new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression); finally this.parseState.pop(); return pointcutDefinition; 后面parseAdvisor、parseAspect也是对不同的元素进行注册,具体代码如下: /* * Parses the supplied code <advisor> element and registers the resulting * link org.springframework.aop.Advisor and any resulting link org.springframework.aop.Pointcut * with the supplied link BeanDefinitionRegistry. */ private void parseAdvisor(Element advisorElement, ParserContext parserContext) AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext); String id = advisorElement.getAttribute(ID); try this.parseState.push(new AdvisorEntry(id); String advisorBeanName = id; if (StringUtils.hasText(advisorBeanName) parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef); else advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef); 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 void parseAspect(Element aspectElement, ParserContext parserContext) String aspectId = aspectElement.getAttribute(ID); String aspectName = aspectElement.getAttribute(REF); try this.parseState.push(new AspectEntry(aspectId, aspectName); List beanDefinitions = new ArrayList(); List beanReferences = new ArrayList(); List declareParents = DomUtils.getChildElementsByTagName(aspectElement, DECLARE_PARENTS); for (int i = METHOD_INDEX; i declareParents.size(); i+) Element declareParentsElement = declareParents.get(i); beanDefinitions.add(parseDeclareParents(declareParentsElement, parserContext); / We have to parse advice and all the advice kinds in one loop, to get the / ordering semantics right. NodeList nodeList = aspectElement.getChildNodes(); boolean adviceFoundAlready = false; for (int i = 0; i nodeList.getLength(); i+) Node node = nodeList.item(i); if (isAdviceNode(node, parserContext) if (!adviceFoundAlready) adviceFoundAlready = true; if (!StringUtils.hasText(aspectName) parserContext.getReaderContext().error( tag needs aspect bean reference via ref attribute when declaring advices., aspectElement, this.parseState.snapshot(); return; beanReferences.add(new RuntimeBeanReference(aspectName); Abstr

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论