配色: 字号:
springAOP入口之AopNamespaceHandler
2016-09-19 | 阅:  转:  |  分享 
  
springAOP入口之AopNamespaceHandler

我们从spring.handlers入口开始看:



http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler

1

打开类AopNamespaceHandler,代码如下:







packageorg.springframework.aop.config;



importorg.springframework.aop.aspectj.AspectJExpressionPointcut;

importorg.springframework.beans.factory.xml.BeanDefinitionParser;

importorg.springframework.beans.factory.xml.NamespaceHandlerSupport;



/

{@codeNamespaceHandler}forthe{@codeaop}namespace.



Providesa{@linkorg.springframework.beans.factory.xml.BeanDefinitionParser}forthe

{@code<aop:config>}tag.A{@codeconfig}tagcanincludenested

{@codepointcut},{@codeadvisor}and{@codeaspect}tags.



The{@codepointcut}tagallowsforcreationofnamed

{@linkAspectJExpressionPointcut}beansusingasimplesyntax:



<aop:pointcutid="getNameCalls"expression="execution(..ITestBean.getName(..))"/>





Usingthe{@codeadvisor}tagyoucanconfigurean{@linkorg.springframework.aop.Advisor}

andhaveitappliedtoallrelevantbeansinyou{@linkorg.springframework.beans.factory.BeanFactory}

automatically.The{@codeadvisor}tagsupportsbothin-lineandreferenced

{@linkorg.springframework.aop.PointcutPointcuts}:





<aop:advisorid="getAgeAdvisor"

pointcut="execution(..ITestBean.getAge(..))"

advice-ref="getAgeCounter"/>



<aop:advisorid="getNameAdvisor"

pointcut-ref="getNameCalls"

advice-ref="getNameCounter"/>



@authorRobHarrop

@authorAdrianColyer

@authorJuergenHoeller

@since2.0

/

publicclassAopNamespaceHandlerextendsNamespaceHandlerSupport{



/

Registerthe{@linkBeanDefinitionParserBeanDefinitionParsers}forthe

''{@codeconfig}'',''{@codespring-configured}'',''{@codeaspectj-autoproxy}''

and''{@codescoped-proxy}''tags.

/

@Override

publicvoidinit(){

//In2.0XSDaswellasin2.1XSD.

registerBeanDefinitionParser("config",newConfigBeanDefinitionParser());

registerBeanDefinitionParser("aspectj-autoproxy",newAspectJAutoProxyBeanDefinitionParser());

registerBeanDefinitionDecorator("scoped-proxy",newScopedProxyBeanDefinitionDecorator());



//Onlyin2.0XSD:movedtocontextnamespaceasof2.1

registerBeanDefinitionParser("spring-configured",newSpringConfiguredBeanDefinitionParser());

}



}



根据注释,该类是aop命名空间的处理类。

利用BeanDefinitionParser解析aop:config标签,该标签包括pointcut、advisor、aspect标签。

pointcut标签允许创建AspectJExpressionPointcut,利用简单的语法:





1

使用advisor标签能够配置org.springframework.aop.Advisor,并且能自动应用的bean对象中。

advisor标签支持内联定义的或者引用的org.springframework.aop.PointcutPointcuts:




pointcut="execution(..ITestBean.getAge(..))"

advice-ref="getAgeCounter"/>




pointcut-ref="getNameCalls"

advice-ref="getNameCounter"/>



再看AopNamespaceHandler的类结构图:

image



接口NamespaceHandler



先上源码:



packageorg.springframework.beans.factory.xml;



importorg.w3c.dom.Element;

importorg.w3c.dom.Node;



importorg.springframework.beans.factory.config.BeanDefinition;

importorg.springframework.beans.factory.config.BeanDefinitionHolder;



/

Baseinterfaceusedbythe{@linkDefaultBeanDefinitionDocumentReader}

forhandlingcustomnamespacesinaSpringXMLconfigurationfile.



Implementationsareexpectedtoreturnimplementationsofthe

{@linkBeanDefinitionParser}interfaceforcustomtop-leveltagsand

implementationsofthe{@linkBeanDefinitionDecorator}interfacefor

customnestedtags.



Theparserwillcall{@link#parse}whenitencountersacustomtag

directlyunderthe{@code<beans>}tagsand{@link#decorate}when

itencountersacustomtagdirectlyundera{@code<bean>}tag.



Developerswritingtheirowncustomelementextensionstypicallywill

notimplementthisinterfacedirectly,butrathermakeuseoftheprovided

{@linkNamespaceHandlerSupport}class.



@authorRobHarrop

@authorErikWiersma

@since2.0

@seeDefaultBeanDefinitionDocumentReader

@seeNamespaceHandlerResolver

/

publicinterfaceNamespaceHandler{



/

Invokedbythe{@linkDefaultBeanDefinitionDocumentReader}after

constructionbutbeforeanycustomelementsareparsed.

@seeNamespaceHandlerSupport#registerBeanDefinitionParser(String,BeanDefinitionParser)

/

voidinit();



/

Parsethespecified{@linkElement}andregisteranyresulting

{@linkBeanDefinitionBeanDefinitions}withthe

{@linkorg.springframework.beans.factory.support.BeanDefinitionRegistry}

thatisembeddedinthesupplied{@linkParserContext}.

Implementationsshouldreturntheprimary{@codeBeanDefinition}

thatresultsfromtheparsephaseiftheywishtobeusednested

inside(forexample)a{@code<property>}tag.

Implementationsmayreturn{@codenull}iftheywill

notbeusedinanestedscenario.

@paramelementtheelementthatistobeparsedintooneormore{@codeBeanDefinitions}

@paramparserContexttheobjectencapsulatingthecurrentstateoftheparsingprocess

@returntheprimary{@codeBeanDefinition}(canbe{@codenull}asexplainedabove)

/

BeanDefinitionparse(Elementelement,ParserContextparserContext);



/

Parsethespecified{@linkNode}anddecoratethesupplied

{@linkBeanDefinitionHolder},returningthedecorateddefinition.

The{@linkNode}maybeeitheran{@linkorg.w3c.dom.Attr}oran

{@linkElement},dependingonwhetheracustomattributeorelement

isbeingparsed.

Implementationsmaychoosetoreturnacompletelynewdefinition,

whichwillreplacetheoriginaldefinitionintheresulting

{@linkorg.springframework.beans.factory.BeanFactory}.

Thesupplied{@linkParserContext}canbeusedtoregisterany

additionalbeansneededtosupportthemaindefinition.

@paramsourcethesourceelementorattributethatistobeparsed

@paramdefinitionthecurrentbeandefinition

@paramparserContexttheobjectencapsulatingthecurrentstateoftheparsingprocess

@returnthedecorateddefinition(toberegisteredintheBeanFactory),

orsimplytheoriginalbeandefinitionifnodecorationisrequired.

A{@codenull}valueisstrictlyspeakinginvalid,butwillbeleniently

treatedlikethecasewheretheoriginalbeandefinitiongetsreturned.

/

BeanDefinitionHolderdecorate(Nodesource,BeanDefinitionHolderdefinition,ParserContextparserContext);



}



该接口是供处理spring的xml配置文件类DefaultBeanDefinitionDocumentReader使用的基接口。

实现类需要返回顶级标签和BeanDefinitionDecorator定义的内嵌标签的实现。

该解析器在遇到自定义的bean标签时会调用parse()和decorate()方法.



抽象类NamespaceHandlerSupport



源码如下:



packageorg.springframework.beans.factory.xml;



importjava.util.HashMap;

importjava.util.Map;



importorg.w3c.dom.Attr;

importorg.w3c.dom.Element;

importorg.w3c.dom.Node;



importorg.springframework.beans.factory.config.BeanDefinition;

importorg.springframework.beans.factory.config.BeanDefinitionHolder;



/

实现了NamespaceHandlers的支持类,通过BeanDefinitionParser和BeanDefinitionDecorator的策略接口解析和装饰

提供了相应的方法注册解析器去处理具体的元素

/

publicabstractclassNamespaceHandlerSupportimplementsNamespaceHandler{



/

保存BeanDefinitionParser的实现

/

privatefinalMapparsers=

newHashMap();



/

保存BeanDefinitionDecorator的实现

/

privatefinalMapdecorators=

newHashMap();



/

根据属性保存BeanDefinitionDecorator的实现

/

privatefinalMapattributeDecorators=

newHashMap();





/

解析Element元素并注册

/

@Override

publicBeanDefinitionparse(Elementelement,ParserContextparserContext){

returnfindParserForElement(element,parserContext).parse(element,parserContext);

}



/

根据Element查找注册的BeanDefinitionParser

/

privateBeanDefinitionParserfindParserForElement(Elementelement,ParserContextparserContext){

StringlocalName=parserContext.getDelegate().getLocalName(element);

BeanDefinitionParserparser=this.parwww.shanxiwang.netsers.get(localName);

if(parser==null){

parserContext.getReaderContext().fatal(

"CannotlocateBeanDefinitionParserforelement["+localName+"]",element);

}

returnparser;

}



/

装饰代理的BeanDefinitionDecorator,被注册用来处理Node

/

@Override

publicBeanDefinitionHolderdecorate(

Nodenode,BeanDefinitionHolderdefinition,ParserContextparserContext){



returnfindDecoratorForNode(node,parserContext).decorate(node,definition,parserContext);

}



/

从注册的实现类找出BeanDefinitionParser,支持Element(s)和Attr(s)

/

privateBeanDefinitionDecoratorfindDecoratorForNode(Nodenode,ParserContextparserContext){

BeanDefinitionDecoratordecorator=null;

StringlocalName=parserContext.getDelegate().getLocalName(node);

if(nodeinstanceofElement){

decorator=this.decorators.get(localName);

}

elseif(nodeinstanceofAttr){

decorator=this.attributeDecorators.get(localName);

}

else{

parserContext.getReaderContext().fatal(

"CannotdecoratebasedonNodesoftype["+node.getClass().getName()+"]",node);

}

if(decorator==null){

parserContext.getReaderContext().fatal("CannotlocateBeanDefinitionDecoratorfor"+

(nodeinstanceofElement?"element":"attribute")+"["+localName+"]",node);

}

returndecorator;

}





/

子类调用注册BeanDefinitionParser来处理具体的元素

/

protectedfinalvoidregisterBeanDefinitionParser(StringelementName,BeanDefinitionParserparser){

this.parsers.put(elementName,parser);

}



/

子类调用注册BeanDefinitionDecorator来处理具体的元素

/

protectedfinalvoidregisterBeanDefinitionDecorator(StringelementName,BeanDefinitionDecoratordec){

this.decorators.put(elementName,dec);

}



/

子类调用注册BeanDefinitionDecorator处理具体的属性

/

protectedfinalvoidregisterBeanDefinitionDecoratorForAttribute(StringattrName,BeanDefinitionDecoratordec){

this.attributeDecorators.put(attrName,dec);

}



}



AopNamespaceHandler.init()



回看AopNamespaceHandler.init()的方法体:

先从解析config元素开始:



registerBeanDefinitionParser("config",newConfigBeanDefinitionParser());

1

注册BeanDefinitionParser解析器,会自动调用该解析器(ConfigBeanDefinitionParser)的parse方法:



//利用内嵌在ParserContext里的BeanDefinition进行注册并解析具体的元素

@Override

publicBeanDefinitionparse(Elementelement,ParserContextparserContext){

//从parserContext里获取复合的组件定义

CompositeComponentDefinitioncompositeDef=

newCompositeComponentDefinition(element.getTagName(),parserContext.extractSource(element));

parserContext.pushContainingComponent(compositeDef);



//自动代理创建者所需的配置,用于支持通过标签创建的BeanDefinitions

//当proxy-target-class=true,将强制进行类的代理

configureAutoProxyCreator(parserContext,element);



ListchildElts=DomUtils.getChildElements(element);

for(Elementelt:childElts){

StringlocalName=parserContext.getDelegate().getLocalName(elt);

if(POINTCUT.equals(localName)){

//解析提供的pointcut并利用BeanDefinitionRegistry注册

parsePointcut(elt,parserContext);

}

elseif(ADVISOR.equals(localName)){

parseAdvisor(elt,parserContext);

}

elseif(ASPECT.equals(localName)){

parseAspect(elt,parserContext);

}

}



parserContext.popAndRegisterContainingComponent();

returnnull;

}



接下来我们看看parsePointcut完成了哪些事情:



/

Parsesthesupplied{@code<pointcut>}andregisterstheresulting

PointcutwiththeBeanDefinitionRegistry.

/

privateAbstractBeanDefinitionparsePointcut(ElementpointcutElement,ParserContextparserContext){

Stringid=pointcutElement.getAttribute(ID);

Stringexpression=pointcutElement.getAttribute(EXPRESSION);



AbstractBeanDefinitionpointcutDefinition=null;



try{

this.parseState.push(newPointcutEntry(id));

//AspectJExpressionPointcut使用给定的表达式创建BeanDefinition

pointcutDefinition=createPointcutDefinition(expression);

pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));



StringpointcutBeanName=id;

//进行注册,切点名称为空时,自动生成

if(StringUtils.hasText(pointcutBeanName)){

parserContext.getRegistry().registerBeanDefinition(pointcutBeanName,pointcutDefinition);

}

else{

pointcutBeanName=parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);

}



//注册切点组件

parserContext.registerComponent(

newPointcutComponentDefinition(pointcutBeanName,pointcutDefinition,expression));

}

finally{

this.parseState.pop();

}



returnpointcutDefinition;

}



后面parseAdvisor、parseAspect也是对不同的元素进行注册,具体代码如下:



/

Parsesthesupplied{@code<advisor>}elementandregisterstheresulting

{@linkorg.springframework.aop.Advisor}andanyresulting{@linkorg.springframework.aop.Pointcut}

withthesupplied{@linkBeanDefinitionRegistry}.

/

privatevoidparseAdvisor(ElementadvisorElement,ParserContextparserContext){

AbstractBeanDefinitionadvisorDef=createAdvisorBeanDefinition(advisorElement,parserContext);

Stringid=advisorElement.getAttribute(ID);



try{

this.parseState.push(newAdvisorEntry(id));

StringadvisorBeanName=id;

if(StringUtils.hasText(advisorBeanName)){

parserContext.getRegistry().registerBeanDefinition(advisorBeanName,advisorDef);

}

else{

advisorBeanName=parserContext.getReaderContext().registerWithGeneratedName(advisorDef);

}



Objectpointcut=parsePointcutProperty(advisorElement,parserContext);

if(pointcutinstanceofBeanDefinition)www.sm136.com{

advisorDef.getPropertyValues().add(POINTCUT,pointcut);

parserContext.registerComponent(

newAdvisorComponentDefinition(advisorBeanName,advisorDef,(BeanDefinition)pointcut));

}

elseif(pointcutinstanceofString){

advisorDef.getPropertyValues().add(POINTCUT,newRuntimeBeanReference((String)pointcut));

parserContext.registerComponent(

newAdvisorComponentDefinition(advisorBeanName,advisorDef));

}

}

finally{

this.parseState.pop();

}

}







privatevoidparseAspect(ElementaspectElement,ParserContextparserContext){

StringaspectId=aspectElement.getAttribute(ID);

StringaspectName=aspectElement.getAttribute(REF);



try{

this.parseState.push(newAspectEntry(aspectId,aspectName));

ListbeanDefinitions=newArrayList();

ListbeanReferences=newArrayList();



ListdeclareParents=DomUtils.getChildElementsByTagName(aspectElement,DECLARE_PARENTS);

for(inti=METHOD_INDEX;i
ElementdeclareParentsElement=declareParents.get(i);

beanDefinitions.add(parseDeclareParents(declareParentsElement,parserContext));

}



//Wehavetoparse"advice"andalltheadvicekindsinoneloop,togetthe

//orderingsemanticsright.

NodeListnodeList=aspectElement.getChildNodes();

booleanadviceFoundAlready=false;

for(inti=0;i
Nodenode=nodeList.item(i);

if(isAdviceNode(node,parserContext)){

if(!adviceFoundAlready){

adviceFoundAlready=true;

if(!StringUtils.hasText(aspectName)){

parserContext.getReaderContext().error(

"tagneedsaspectbeanreferencevia''ref''attributewhendeclaringadvices.",

aspectElement,this.parseState.snapshot());

return;

}

beanReferences.add(newRuntimeBeanReference(aspectName));

}

AbstractBeanDefinitionadvisorDefinition=parseAdvice(

aspectName,i,aspectElement,(Element)node,parserContext,beanDefinitions,beanReferences);

beanDefinitions.add(advisorDefinition);

}

}



AspectComponentDefinitionaspectComponentDefinition=createAspectComponentDefinition(

aspectElement,aspectId,beanDefinitions,beanReferences,parserContext);

parserContext.pushContainingComponent(aspectComponentDefinition);



Listpointcuts=DomUtils.getChildElementsByTagName(aspectElement,POINTCUT);

for(ElementpointcutElement:pointcuts){

parsePointcut(pointcutElement,parserContext);

}



parserContext.popAndRegisterContainingComponent();

}

finally{

this.parseState.pop();

}

}



现在对aspectj-autoproxy元素的注册解析进行解读:



registerBeanDefinitionParser("aspectj-autoproxy",newAspectJAutoProxyBeanDefinitionParser());

1

从这行代码可以看出,切面自动代理bean的定义解析器为AspectJAutoProxyBeanDefinitionParser。

同样,先看下该解析器的parse方法:



@Override

publicBeanDefinitionparse(Elementelement,ParserContextparserContext){

AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext,element);

extendBeanDefinition(element,parserContext);

returnnull;

}



该方法也只是解析并注册BeanDefinition,包括注解的自动代码创建者。



scoped-proxy元素



registerBeanDefinitionDecorator("scoped-proxy",newScopedProxyBeanDefinitionDecorator());

1

装饰器用ScopedProxyBeanDefinitionDecorator,来看看装饰方法:



@Override

publicBeanDefinitionHolderdecorate(Nodenode,BeanDefinitionHolderdefinition,ParserContextparserContext){

booleanproxyTargetClass=true;

if(nodeinstanceofElement){

Elementele=(Element)node;

if(ele.hasAttribute(PROXY_TARGET_CLASS)){

proxyTargetClass=Boolean.valueOf(ele.getAttribute(PROXY_TARGET_CLASS));

}

}



//Registertheoriginalbeandefinitionasitwillbereferencedbythescopedproxy

//andisrelevantfortooling(validation,navigation).

BeanDefinitionHolderholder=

ScopedProxyUtils.createScopedProxy(definition,parserContext.getRegistry(),proxyTargetClass);

StringtargetBeanName=ScopedProxyUtils.getTargetBeanName(definition.getBeanName());

parserContext.getReaderContext().fireComponentRegistered(

newBeanComponentDefinition(definition.getBeanDefinition(),targetBeanName));

returnholder;

}



从代码可以看出,默认对目标类进行代理。

利用工具ScopedProxyUtils创建代理的处理对象。

处理代码如下:



/

Generateascopedproxyforthesuppliedtargetbean,registeringthetarget

beanwithaninternalnameandsetting''targetBeanName''onthescopedproxy.

@paramdefinitiontheoriginalbeandefinition

@paramregistrythebeandefinitionregistry

@paramproxyTargetClasswhethertocreateatargetclassproxy

@returnthescopedproxydefinition

/

publicstaticBeanDefinitionHoldercreateScopedProxy(BeanDefinitionHolderdefinition,

BeanDefinitionRegistryregistry,booleanproxyTargetClass){



StringoriginalBeanName=definition.getBeanName();

BeanDefinitiontargetDefinition=definition.getBeanDefinition();

StringtargetBeanName=getTargetBeanName(originalBeanName);



//Createascopedproxydefinitionfortheoriginalbeanname,

//"hiding"thetargetbeaninaninternaltargetdefinition.

RootBeanDefinitionproxyDefinition=newRootBeanDefinition(ScopedProxyFactoryBean.class);

proxyDefinition.setDecoratedDefinition(newBeanDefinitionHolder(targetDefinition,targetBeanName));

proxyDefinition.setOriginatingBeanDefinition(targetDefinition);

proxyDefinition.setSource(definition.getSource());

proxyDefinition.setRole(targetDefinition.getRole());



proxyDefinition.getPropertyValues().add("targetBeanName",targetBeanName);

if(proxyTargetClass){

targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE,Boolean.TRUE);

//ScopedProxyFactoryBean''s"proxyTargetClass"defaultisTRUE,sowedon''tneedtosetitexplicitlyhere.

}

else{

proxyDefinition.getPropertyValues().add("proxyTargetClass",Boolean.FALSE);

}



//Copyautowiresettingsfromoriginalbeandefinition.

proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());

proxyDefinition.setPrimary(targetDefinition.isPrimary());

if(targetDefinitioninstanceofAbstractBeanDefinition){

proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition)targetDefinition);

}



//Thetargetbeanshouldbeignoredinfavorofthescopedproxy.

targetDefinition.setAutowireCandidate(false);

targetDefinition.setPrimary(false);



//Registerthetargetbeanasseparatebeaninthefactory.

registry.registerBeanDefinition(targetBeanName,targetDefinition);



//Returnthescopedproxydefinitionasprimarybeandefinition

//(potentiallyaninnerbean).

returnnewBeanDefinitionHolder(proxyDefinition,originalBeanName,definition.getAliases());

}

献花(0)
+1
(本文系网络学习天...首藏)