<aop:config> Label parsing
The parser for the AOP namespace is Aopnamespacehandler
Here we can see a few parsers registered, focusing on Configbeandefinitionparser
In the parse method of Configbeandefinitionparser, the following three direct sub-tags pointcut, advisor, Aspect, respectively, are parsed aop:config
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 Label parsing
PrivateAbstractbeandefinition 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));
Create Beandefinition, below pointcutdefinition = createpointcutdefinition (expression); Pointcutdefinition.setsource (Parsercontext.extractsource (pointcutelement)); String pointcutbeanname = id; if (Stringutils.hastext (pointcutbeanname)) {
//This is the registered bean Parsercont Ext.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; }
We can see that the beanclass of Rootbeandefinition is Aspectjexpressionpointcut, that is, Getbean will instantiate Aspectjexpressionpointcut, and set a property value for it expression such as execution (* com.wjz.service.*.* (..))
Let's take a look at the inheritance structure of aspectjexpressionpointcut. This class implements both the Classfilter and Methodmatcher interfaces to perform class matching and method matching logic. It has an expression property to set expressions, and ASPECTJ will eventually parse the expression into a Pointcutexpression object to perform the related semantics. The following article is detailed
Aspect label parsing
The parsing of the aspect tag is relatively complex, parsing all the notification sub-labels (aop:before, aop:after, etc.) below it
String Aspectid =Aspectelement.getattribute (ID); String Aspectname =Aspectelement.getattribute (REF);
Get all Notifications sub-label NodeList NodeList =Aspectelement.getchildnodes (); Boolean Advicefoundalready = False; for (int i = 0; i < nodelist.getlength (); i++) {Node node =Nodelist.item (i);
Determine if the notification label is 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));}
Parse and register the notification sub-label, following the detailed 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))); The method attribute of the notification tag is parsed into a methodlocatingfactorybean type Bean, and the MethodName property value is set to
// Prepare for the formal parameters of a constructor such as Aspectjmethodbeforeadvice
rootbeandefinition methoddefinition = new Rootbeandefinition (MethodL Ocatingfactorybean.class ); Methoddefinition.getpropertyvalues (). Add ("Targetbeanname" , aspectname); methoddefinition.getpropertyvalues (). Add ("MethodName", Adviceelement.getattribute ("method" )); Methoddefinition.setsynthetic (true );// Create an instance of Aspectinstancefactory to prepare the formal parameters for constructors such as Aspectjmethodbeforeadvice
Rootbeandefinition aspectfactorydef = new Rootbeandefinition (simplebeanfactoryawareaspectinstancefactory.class); Aspectfactorydef.getpropertyvalues (). Add ("Aspectbeanname", aspectname); Aspectfactorydef.setsynthetic (True); Prepare the constructor for Aspectjmethodbeforeadvice, and then abstractbeandefinition advicedef = createadvicedefinition (adviceelement, ParserContext, Aspectname, order, methoddefinition, Aspec Tfactorydef, Beandefinitions, beanreferences); The resolution notification sub-label is Aspectjpointcutadvisor object rootbeandefinition advisordefinition = new Rootbeandefinition (ASPECTJPOINTC Utadvisor.class ); Advisordefinition.setsource (Parsercontext.extractsource (adviceelement));
//Set constructor parameter information for Abstractaspectjadvice in Aspectjpointcutadvisor advisordefinition.getconstructorargument Values (). Addgenericargumentvalue (Advicedef); If (Aspectelement.hasattribute (Order_property)) {advisordefinition.getpropertyvalues (). Add (ORDER_PROPERTY, Aspectelement.getattribute (Order_property)); }//Register notification sub-label Parsercontext.getreadercontext (). Registerwithgeneratedname (advisordefinition); return Advisordefinition; Finally {this . Parsestate.pop ();}}
PrivateAbstractbeandefinition createadvicedefinition (Element adviceelement, ParserContext parsercontext, String aspec Tname, intOrder, Rootbeandefinition MethodDef, Rootbeandefinition aspectfactorydef, list<beandefinition> Beandefinitions, list<beanreference>beanreferences) {//Getadviceclass () method get Aspectjmethodbeforeadvice, Aspectjafterreturningadvice, etc. RootBeanDefinit Ion advicedefinition = newRootbeandefinition (Getadviceclass (adviceelement, ParserContext)); Advicedefinition.setsource (Parsercontext.extractsource (adviceelement)); Add attribute Value 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 (R eturning)); } 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));} Prepare the parameters required for the constructor such as Aspectjmethodbeforeadvice, prepare the Aspectjmethodbeforeadvice for the reflection of the constructor constructorargumentvalues CAV =advicedefinition.getconstructorargumentvalues (); Cav.addindexedargumentvalue (Method_index, METHODDEF); Get Pointcut-ref Property value 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) point CUT); Cav.addindexedargumentvalue (Pointcut_index, pointcutref); Beanreferences.add (POINTCUTREF); } cav.addindexedargumentvalue (Aspect_instance_factory_index, aspectfactorydef); return advicedefinition;}
The constructor for the Aspectjmethodbeforeadvice is
Advisor Tag Parsing
private voidParseadvisor (Element advisorelement, ParserContext parsercontext) {
Create the advisor tag corresponding to the beandefinition, followed by a detailed abstractbeandefinition advisordef =Createadvisorbeandefinition (Advisorelement, ParserContext); String ID =Advisorelement.getattribute (ID); Try{This.parseState.push (newAdvisorentry (ID)); String Advisorbeanname = ID;
//Register Bean if (Stringutils.hastext (advisorbeanname)) {parsercontext.getregistry (). registerbeandefinition (Advisorbeanname, Advisordef); } else {advisorbeanname = parsercontext.getreadercontext (). Registerwithgeneratedname (advisordef);} Get the Pointcut-ref property value, add the property 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 ();}}
PrivateAbstractbeandefinition createadvisorbeandefinition (Element advisorelement, ParserContext ParserContext) {
Getbean when instantiating a defaultbeanfactorypointcutadvisor rootbeandefinition advisordefinition = new RootBeanDefinition (Def Aultbeanfactorypointcutadvisor.class); Advisordefinition.setsource (Parsercontext.extractsource (advisorelement)); String adviceref = advisorelement.getattribute (advice_ref); if (! Stringutils.hastext (Adviceref)) {Parsercontext.getreadercontext (). Error ("' Advice-ref ' attr Ibute contains empty value. ", Advisorelement, this. Parsestate.snapshot ()); } else {advisordefinition.getpropertyvalues (). Add (Advice_bean_name, New runtimebeannamereference (adviceRe f)); } If (Advisorelement.hasattribute (Order_property)) {advisordefinition.getpropertyvalues (). Add (ORDER_PROPERTY, Advisorelement.getattribute (Order_property)); } return advisordefinition;}
A detailed XML approach to the parsing of spring AOP