Spring source Analysis (ix)--AOP

Source: Internet
Author: User

We know that there are some drawbacks to using object-oriented programming (OOP), when it is necessary to introduce the same common behavior for multiple objects that do not have an inheritance relationship, such as logging, security detection, etc., we can only refer to the public behavior in each object, so that the program produces a lot of duplicate code, the program is inconvenient to maintain, So there is a complement to object-oriented programming, that is, aspect-oriented programming (AOP), where AOP focuses on landscape and differs from the vertical orientation of oop.

Spring 2.0 uses @aspectj annotations to label the Pojo to define a facet that contains the Pointcut information and enhances the crosscutting logic. Spring2.0 can weave this facet into a matching target bean. @AspectJ annotations Use the ASPECTJ pointcut expression syntax for pointcut definitions, which can be defined by pointcuts with advanced features such as pointcut functions, operators, and wildcard characters, with a strong connection point description capability.

One: Dynamic AOP use example

(1) Creating a bean for interception

In practice, this bean may be the core logic to meet the business needs, such as the test method may encapsulate this core business, but if we want to add a log before and after test to track debugging, if the direct modification of the source code does not conform to the object-oriented design method, And the arbitrary modification of the original code will also cause a certain risk, fortunately, the next spring to help us do this.

 Public class Testbean {    private String teststr = "Teststr";      Public String getteststr () {        return  teststr;    }      Public void setteststr (String teststr) {        this. teststr = teststr;    }       Public void Test () {        System.out.println ("test");}    }

(2) Create advisor.

The use of @aspectj annotations to annotate Pojo with the most primitive and cumbersome configuration in spring simplifies the work of AOP, for example, in the Aspectjtest class, All we have to do is print the beforetest in the console before the test method of all the classes executes, and print the aftertest after all the class's test methods are executed, and then use wrapping to print before1 and After1 separately before and after the methods of all classes are executed.

@Aspect Public classaspectjtest {@Pointcut ("Execution (* *.test (..))")     Public voidTest () {} @Before ("Test ()")     Public voidbeforetest () {System.out.println ("Beforetest"); } @After ("Test ()")     Public voidaftertest () {System.out.println ("Aftertest"); }     PublicObject arounttest (Proceedingjoinpoint p) {System.out.println ("Before1"); Object obj=NULL; Try{obj=p.proceed (); }Catch(Throwable e) {e.printstacktrace (); } System.out.println ("After1"); returnobj; }}

(3) Creating a configuration file

Although annotations can replace XML configurations, this article opens up the AOP functionality through XML configuration to provide a more detailed explanation for understanding.

<?XML version= "1.0" encoding= "UTF-8"?><BeansXmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance"xmlns= "Http://www.springframework.org/schema/beans"XMLNS:AOP= "HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP"xsi:schemalocation= "Http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/ Spring-beans-3.0.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP http://www.springframework.org/schema/aop/ Spring-aop.xsd ">    <Aop:aspectj-autoproxy></Aop:aspectj-autoproxy>    <BeanID= "Test"class= "Test. Testbean " ></Bean>    <Beanclass= "Test. Aspectjtest " ></Bean></Beans>

(4) test

 Public Static void Main (string[] args) {        new classpathxmlapplicationcontext ("Aspecttest.xml");         = (Testbean) bf.getbean ("Test");        Bean.test ();    }

(5) Results

Beforetest

Before1

Test

Aftertest

After1

Spring implements an increase in the test method for all classes so that accessibility can be independent of the core business and facilitates the extension and decoupling of programs.

So how does spring actually implement AOP? First we know whether spring supports annotated AOP is controlled by a configuration file, that is, <aop:aspectj--autoproxy/> When this configuration is declared in a configuration file, Spring supports annotated AOP. Then our analysis begins with this annotation.

Two: Dynamic AOP custom Labels

The custom annotations in spring have been mentioned before, and if a custom annotation is declared, the corresponding parser must be registered somewhere in the program. The search finds that a function in Aopnamespacehander corresponds to this:

 Public classAopnamespacehandlerextendsNamespacehandlersupport {/*** Register the {@linkBeandefinitionparser Beandefinitionparsers} for the * ' {@codeconfig} ', ' {@codespring-configured} ', ' {@codeAspectj-autoproxy} ' * and ' {@codeScoped-proxy} ' tags. */@Override Public voidinit () {//In 2.0 XSD as well as in 2.1 xsd.Registerbeandefinitionparser ("config",NewConfigbeandefinitionparser ()); Registerbeandefinitionparser ("Aspectj-autoproxY ",New aspectjautoproxybeandefinitionparser()); Registerbeandefinitiondecorator ("Scoped-proxy",Newscopedproxybeandefinitiondecorator ()); //2.0 xsd:moved to context namespace as of 2.1Registerbeandefinitionparser ("spring-configured",NewSpringconfiguredbeandefinitionparser ()); }}

We can tell that when parsing a configuration file, the parser Aspectjautoproxybeandefinitionparser is used to parse the aspectj-autoproxy annotation as soon as it is encountered. Here's a look at Aspectjautoproxybeandefinitionparser's internal implementation.

(2.1) Registration Annotationawareaspectjautoproxycreator

all parsers, because it is a unified implementation of the Beandefinitionparser interface, the entry is started from the parse function , Aspectjautoproxybeandefinitionparser's parse function is as follows:

classAspectjautoproxybeandefinitionparserImplementsBeandefinitionparser {@Override Publicbeandefinition Parse(element element, ParserContext ParserContext) {aopnamespaceutils.         Registeraspectjannotationautoproxycreatorifnecessary(parsercontext, Element);        Extendbeandefinition (element, parsercontext); return NULL; }    Private voidextendbeandefinition (element element, ParserContext parsercontext) {beandefinition beandef=parsercontext.getregistry (). Getbeandefinition (Aopconfigutils.auto_proxy_creator_bean_name); if(Element.haschildnodes ()) {Addincludepatterns (element, ParserContext, beandef); }    }    Private voidAddincludepatterns (element element, ParserContext ParserContext, beandefinition beandef) {managedlist<TypedStringValue> IncludePatterns =NewManagedlist<typedstringvalue>(); NodeList ChildNodes=element.getchildnodes ();  for(inti = 0; I < childnodes.getlength (); i++) {node node=Childnodes.item (i); if(nodeinstanceofElement) {Element includeelement=(Element) node; Typedstringvalue Valueholder=NewTypedstringvalue (Includeelement.getattribute ("name"));                Valueholder.setsource (Parsercontext.extractsource (includeelement));            Includepatterns.add (Valueholder); }        }        if(!Includepatterns.isempty ())            {Includepatterns.setsource (Parsercontext.extractsource (Element)); Beandef.getpropertyvalues (). Add ("IncludePatterns", IncludePatterns); }    }}

Where the Registeraspectjannotationautoproxycreatorifnecessary function is our concern, but also the implementation of the key logic.

/*** @authorRob Harrop *@authorJuergen Hoeller *@authorMark Fisher *@since2.0 *@seeaopconfigutils*/ Public Abstract classAopnamespaceutils {/*** The {@codeProxy-target-class} attribute as found on aop-related XML tags. */     Public Static FinalString Proxy_target_class_attribute = "Proxy-target-class"; /*** The {@codeExpose-proxy} attribute as found on aop-related XML tags. */    Private Static FinalString Expose_proxy_attribute = "Expose-proxy";  Public Static voidregisterautoproxycreatorifnecessary (ParserContext parsercontext, Element sourceelement) {Beandefi Nition beandefinition=aopconfigutils.registerautoproxycreatorifnecessary (Parsercontext.getregistry (), parserContext.extract        Source (sourceelement));        Useclassproxyingifnecessary (Parsercontext.getregistry (), sourceelement);    Registercomponentifnecessary (Beandefinition, ParserContext); }     Public Static voidregisteraspectjautoproxycreatorifnecessary (ParserContext parsercontext, Element sourceelement) {B Eandefinition beandefinition=aopconfigutils.registeraspectjautoproxycreatorifnecessary (Parsercontext.getregistry (), ParserContext.        Extractsource (sourceelement));        Useclassproxyingifnecessary (Parsercontext.getregistry (), sourceelement);    Registercomponentifnecessary (Beandefinition, ParserContext); }     Public Static void registeraspectjannotationautoproxycreatorifnecessary(parsercontext parsercontext, Element source Element) {beandefinition beandefinition=Aopconfigutils. registeraspectjannotationautoproxycreatorifnecessary (Parsercontext.getregistry (), Parsercontext.extractsource (sourceelement));
//For handling Proxy-target-class and Expose--proxy properties useclassproxyingifnecessary (Parsercontext.getregistry (), sourceelement);
Registering components and notifying them for further processing by the listener
Where Beandefinition's classname is Annotationawareaspectjautoproxycreator registercomponentifnecessary (beanDefinition , ParserContext); } Private Static void useclassproxyingifnecessary(beandefinitionregistry Registry, Element sourceelement) {if(Sourceelement! =NULL) { BooleanProxytargetclass =boolean.valueof (Sourceelement.getattribute (Proxy_target_class_attribute)); if(Proxytargetclass) {aopconfigutils.forceautoproxycreatortouseclassproxying (registry); } BooleanExposeproxy =boolean.valueof (Sourceelement.getattribute (Expose_proxy_attribute)); if(exposeproxy) {Aopconfigutils.forceautoproxycreatortoexposeproxy (registry); } } } Private Static void registercomponentifnecessary(beandefinition beandefinition, ParserContext parsercontext) {if(Beandefinition! =NULL) {beancomponentdefinition componentdefinition=Newbeancomponentdefinition (beandefinition, aopconfigutils.auto_proxy_creator_bean_name); Parsercontext.registercomponent (componentdefinition); } }}

There are 3 main things done in the Registeraspectjannotationautoproxycreatorifnecessary method, and basically every line of code is a complete logic.

1. Register or upgrade Annotationawareaspectjautoproxycreator

The implementation of AOP is basically done by Annotationawareaspectjautoproxycreator, which can automatically proxy matching beans based on the pointcut defined by the @point annotation.

Spring source Analysis (ix)--AOP

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.