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());
}
|