Knowledge of Spring Source learning AOP

Source: Internet
Author: User
Tags aop assert reflection throwable
Preface

As one of the important features of spring, the role of AOP is of course unquestionable. It allows us to cut through the code during the execution of the code, encapsulating the actions that are performed repeatedly. Ensure the modularity and ease of management of your code. This blog post will explain how AOP works and uses it from a source point of view:

a simple AOP implementation

<!--bean.xml to
<bean id= "Testadvice" class= "CHAPTER3_AOP. Testadvice "></bean>
<bean id=" AOP "class=" Org.springframework.aop.framework.ProxyFactoryBean " >
        <!--optional
        --<property name= "proxyinterfaces" >
            <value>chapter3_aop. operateapi</value>
        </property>
        <property name= "target" >
            <bean class= "chapter3_ Aop. Operatetarget "></bean>
        </property>
        <property name=" Interceptornames ">
            < list>
                <value>testadvice</value>
            </list>
        </property>
    </bean >
Operatetarget.java public 
class Operatetarget implements operateapi{
    @Override public
    Void Update () {
        System.out.println ("Update");
    }
}
Testadvice.java public
class Testadvice implements methodbeforeadvice{

    @Override public
    Void before ( method, object[] args, Object target) throws Throwable {
        System.out.println ("Prehandle");}

}
Client.java public
class Client {public
    static void main (String []args) {
        ApplicationContext ac = new Cl Asspathxmlapplicationcontext ("Bean.xml");
        Operateapi API = (OPERATEAPI) ac.getbean ("AOP");
        Api.update ();
    }
}
Output
prehandle
update
AOP Process 1. Generating proxy objects

The implementation of

Proxyfactorybean is the bottom-up approach to creating AOP in the spring IOC environment and is the most flexible approach. So through the use of Proxyfactorybean, look at the process of how AOP works.

Proxyfactorybean.java//Gets the generated proxy object public Object GetObject () throws Beansexception {Initializeadvisorchain ();
        if (Issingleton ()) {return getsingletoninstance (); } else {if (this.targetname = = null) {Logger.warn ("Using Non-singleton proxies with Singleton targets is often undesirable.
            "+" Enable prototype proxies by setting the ' TargetName ' property. ");
        return Newprototypeinstance ();
        }}//Create interceptor chain private synchronized void Initializeadvisorchain () throws Aopconfigexception, Beansexception {
        If it has already been initialized, return directly if (this.advisorchaininitialized) {return; } if (! Objectutils.isempty (This.interceptornames)) {if (this.beanfactory = = null) {throw new Illega Lstateexception ("No beanfactory available anymore (probably due to serialization)" + "-cannot re SoLve Interceptor Names "+ arrays.aslist (this.interceptornames));
                    } if (This.interceptornames[this.interceptornames.length-1].endswith (global_suffix) && This.targetname = = NULL && This.targetsource = = Empty_target_source) {throw new Aopconfige
            Xception ("Target required after Globals"); }//Traversal set interceptor for (String name:this.interceptorNames) {if (logger.istraceenabl
                Ed ()) {logger.trace ("Configuring advisor or advice '" + name + "'"); } if (Name.endswith (Global_suffix)) {if (!) (
                                This.beanfactory instanceof Listablebeanfactory) {throw new Aopconfigexception (
                    "Can only use global advisors or interceptors with a listablebeanfactory");
     }//Add all global interceptors, the main process is to find all the advisors and interceptor in Beanfactory,             Added to Advisors addglobaladvisor ((listablebeanfactory) This.beanfactory,
                Name.substring (0, Name.length ()-global_suffix.length ()));
                    } else {Object advice;
                        if (This.singleton | | This.beanFactory.isSingleton (name)) {//Pre-parsed from Beanfactory directly gets the object
                    Advice = This.beanFactory.getBean (name);
                    } else {advice = new prototypeplaceholderadvisor (name);
                } addadvisoronchaincreation (advice, name);
    }}} this.advisorchaininitialized = true; }//Add Interceptor private void Addadvisoronchaincreation (Object Next, String name) {//Convert the obtained class to advisor.
        If it is advice, generate a new Advisor Advisor advisor with advice as a parameter = Namedbeantoadvisor (next);
   if (logger.istraceenabled ()) {         Logger.trace ("Adding Advisor with Name '" + name + "'");
    } addadvisor (advisor);
            }//Get singleton instance private synchronized Object getsingletoninstance () {if (this.singletoninstance = = null) {
            Gets the instance according to the set TargetName and wraps it in Targetsource This.targetsource = Freshtargetsource ();
                if (this.autodetectinterfaces && getproxiedinterfaces (). Length = = 0 &&!isproxytargetclass ()) {
                Get Class class<?> Targetclass = Gettargetclass ();  if (Targetclass = = null) {throw new Factorybeannotinitializedexception ("cannot determine target class
                For proxy "); }//Get all the superclass interfaces and set to interface properties in Setinterfaces (Classutils.getallinterfacesforclass (targetclass, th
            Is.proxyclassloader));
            }//Initialize the shared singleton instance.
            Super.setfrozen (This.freezeproxy);
    Key to generating proxy instances        This.singletoninstance = GetProxy (Createaopproxy ());
    } return this.singletoninstance;
        } Private synchronized Object newprototypeinstance () {//In the case of a prototype, we need to give the proxy
        An independent instance of the configuration. In this case, no proxy would have a instance of this object's configuration,//But would have a independent co
        Py.
        if (logger.istraceenabled ()) {logger.trace ("Creating copy of Prototype Proxyfactorybean config:" + this);
        } proxycreatorsupport copy = new Proxycreatorsupport (Getaopproxyfactory ());
        The copy needs a fresh advisor chain, and a fresh targetsource.
        Targetsource Targetsource = Freshtargetsource ();
        Copy.copyconfigurationfrom (This, Targetsource, Freshadvisorchain ());
            if (this.autodetectinterfaces && getproxiedinterfaces (). Length = = 0 &&!isproxytargetclass ()) { Rely onAOP infrastructure to the US what interfaces to proxy. Copy.setinterfaces (Classutils.getallinterfacesforclass (Targetsource.gettargetclass (), This.proxyClass
        Loader));

        } copy.setfrozen (This.freezeproxy);
        if (logger.istraceenabled ()) {logger.trace ("Using proxycreatorsupport copy:" + copy);
    } return GetProxy (Copy.createaopproxy ());
        } Protected final synchronized Aopproxy Createaopproxy () {if (!this.active) {activate ();
    } return Getaopproxyfactory (). Createaopproxy (this); }//Defaultaopproxyfactory.java @Override public aopproxy createaopproxy (advisedsupport config) throws Aopco nfigexception {if (config.isoptimize () | | | config.isproxytargetclass () | | | hasnousersuppliedproxyinterfaces (config)
            ) {class<?> Targetclass = Config.gettargetclass (); if (Targetclass = = null) {throw new AopconfigeXception ("Targetsource cannot determine target class:" + "either an interface or a target is requ
            Ired for proxy creation. "); If it is an interface class or proxy class, use the JDK dynamic proxy if (Targetclass.isinterface () | | |
            Proxy.isproxyclass (Targetclass)) {return new Jdkdynamicaopproxy (config);
        } return new Objenesiscglibaopproxy (config);
        } else {return new Jdkdynamicaopproxy (config); }}//Depending on what kind of proxy the aopporxy is, the method of generating the object is different protected object GetProxy (Aopproxy aopproxy) {return Aopproxy.getpro
    XY (This.proxyclassloader); }
    Advisorsupport.java//The main function of the following code is to add the acquired advisor to the advisors linked list, supplemented by clearing the cache @Override public void Addadvisor (Adviso
        R Advisor) {int pos = this.advisors.size ();
    Addadvisor (POS, advisor); } @Override public void addadvisor (int pos, advisor Advisor) throws Aopconfigexception {if (Advisor Inst
        Anceof introductionadvisor) {validateintroductionadvisor (introductionadvisor) advisor);
    } addadvisorinternal (POS, advisor); } private void Addadvisorinternal (int pos, advisor Advisor) throws Aopconfigexception {Assert.notnull (adviso
        R, "Advisor must not is null");
        if (IsFrozen ()) {throw new Aopconfigexception ("Cannot add advisor:configuration is frozen."); } if (pos > This.advisors.size ()) {throw new IllegalArgumentException ("Illega
        L Position "+ pos +" in the Advisor list with size "+ this.advisors.size ()); } this.Advisors.add (POS, advisor);
        Updateadvisorarray ();
    Advicechanged ();
     }/** * Bring the array up to date with the list. */protected final void Updateadvisorarray () {This.advisorarray = This.advisors.toArray (New Advisor[this.advi
    Sors.size ()]);
    } protected void Advicechanged () {this.methodCache.clear (); }

Here's how the JDK dynamic agent and Cglib dynamic agents generate proxy objects:

JDK Dynamic Agent

Public Object GetProxy (ClassLoader ClassLoader) {
    if (logger.isdebugenabled ()) {
        logger.debug ("Creating JDK Dynamic Proxy:target Source is "+ this.advised.getTargetSource ());
    }
    class<?>[] proxiedinterfaces = aopproxyutils.completeproxiedinterfaces (this.advised);
    Finddefinedequalsandhashcodemethods (proxiedinterfaces);
        Generates a proxy class by reflection based on the class loader and interface
    return Proxy.newproxyinstance (ClassLoader, proxiedinterfaces, this);
}

cglib Dynamic Agent

Public Object GetProxy (ClassLoader ClassLoader) {if (logger.isdebugenabled ()) {Logger.debug ("Creating CGLIB
    Proxy:target source is "+ this.advised.getTargetSource ());
        } try {class<?> rootclass = This.advised.getTargetClass ();

        Assert.state (Rootclass! = NULL, "Target class must is available for creating a CGLIB proxy");
        class<?> proxysuperclass = Rootclass;
            if (Classutils.iscglibproxyclass (Rootclass)) {Proxysuperclass = Rootclass.getsuperclass ();
            class<?>[] additionalinterfaces = rootclass.getinterfaces (); for (class<?> additionalinterface:additionalinterfaces) {this.advised.addInterface (additionalinte
            Rface);
        }}//Validate the class, writing log messages as necessary.

        Validateclassifnecessary (Proxysuperclass, ClassLoader);
        Configure CGLIB Enhancer ...
     Enhancer enhancer = Createenhancer ();   if (ClassLoader! = null) {Enhancer.setclassloader (ClassLoader); if (ClassLoader instanceof smartclassloader && ((smartclassloader) classLoader). Isclassreloada
            BLE (proxysuperclass)) {Enhancer.setusecache (false);
        }} enhancer.setsuperclass (Proxysuperclass);
        Enhancer.setinterfaces (Aopproxyutils.completeproxiedinterfaces (this.advised));
        Enhancer.setnamingpolicy (springnamingpolicy.instance);

        Enhancer.setstrategy (New Classloaderawareundeclaredthrowablestrategy (ClassLoader));
        Callback[] callbacks = Getcallbacks (Rootclass);
        class<?>[] types = new class<?>[callbacks.length];
        for (int x = 0; x < types.length; × x + +) {Types[x] = Callbacks[x].getclass (); }//Fixedinterceptormap only populated at the "after Getcallbacks" call above ENHANCER.SETCALLBACKF
             Ilter (New Proxycallbackfilter (   This.advised.getConfigurationOnlyCopy (), This.fixedinterceptormap, This.fixedinterceptoroffset));

        Enhancer.setcallbacktypes (types);
        Generate the proxy class and create a proxy instance.
    return createproxyclassandinstance (enhancer, callbacks); } catch (Codegenerationexception ex) {throw new Aopconfigexception ("Could not generate CGLIB subclass of Clas s ["+ this.advised.getTargetClass () +"]: "+" Common causes of this problem include usin
    G A final class or a non-visible class ", ex); } catch (IllegalArgumentException ex) {throw new Aopconfigexception ("Could not generate CGLIB subclass of CLA SS ["+ This.advised.getTargetClass () +"]: "+" Common causes of this problem include USI
    Ng a final class or a non-visible class ", ex); } catch (Exception ex) {//Targetsource.gettarget () failed throw new AopconfigexCeption ("Unexpected AOP exception", ex); }
}

The above is the process of implementing the Build proxy object, and the interceptor's steps are the callbacks of the two proxies. Then the next step is to drill down to execute the callback code to achieve the Interceptor function. 2. Create an intercept chain

Take the JDK dynamic proxy callback as an example to see how to generate an intercept chain for the target object

The callback method of the JDK dynamic Agent @Override public object Invoke (object proxy, method, object[] args) throws Throwable {
        Methodinvocation invocation;
        Object oldproxy = null;
        Boolean setproxycontext = false;
        Gets the target proxy object Targetsource targetsource = This.advised.targetSource;
        Class<?> targetclass = null;

        Object target = null; try {if (!this.equalsdefined && Aoputils.isequalsmethod (method)) {//if the target class does not implement equal,
                Implemented here.
            Return equals (Args[0]); } if (!this.hashcodedefined && Aoputils.ishashcodemethod (method)) {//If Hashcode is not implemented (
            ) return hashcode ();
                    } if (!this.advised.opaque && method.getdeclaringclass (). Isinterface () && Method.getdeclaringclass (). IsAssignableFrom (Advised.class)) {//Call the method by reflection and execute return Aoputi Ls.invokejoinpoiNtusingreflection (this.advised, method, args);

            } Object RetVal;
                if (this.advised.exposeProxy) {//Make invocation available if necessary.
                Oldproxy = Aopcontext.setcurrentproxy (proxy);
            Setproxycontext = true; }//May is null.
            Get as late as possible to minimize the time we ' own ' the target,//In case it comes from a pool.
            target = Targetsource.gettarget ();
            if (target! = null) {Targetclass = Target.getclass (); }//Here get the object all the Intercept chain list<object> chain = This.advised.getInterceptorsAndDynamicInterceptionAd

            Vice (method, Targetclass); If there is no intercept chain, or if there is no corresponding enhanced if (Chain.isempty ()) {//directly using reflection to execute Object method object[] Argstous
                E = Aopproxyutils.adaptargumentsifnecessary (method, args); RetVal = aoputils.invokejoinpointusingreflection (tArget, method, Argstouse); } else {//otherwise new reflectivemethodinvocation, followed by the method of intercepting chain invocation = new Reflect
                Ivemethodinvocation (proxy, Target, method, args, Targetclass, chain);
                Proceed to the Joinpoint through the interceptor chain.
            RetVal = Invocation.proceed ();
            }//Massage return value if necessary.
            class<?> returntype = Method.getreturntype (); if (retVal! = null && RetVal = = Target && returntype.isinstance (proxy) &&! RawTargetAccess.class.isAssignableFrom (Method.getdeclaringclass ())) {//Special case:it returned "this" And the return type of the method//Is type-compatible.
                Note that we can ' t help if the target sets//a reference to itself in another returned object.
            RetVal = proxy; } else if (RetVal = = nulL && returntype! = Void.type && returntype.isprimitive ()) {throw new Aopinvocationexcepti
            On ("Null return value from advice does not match primitive return type for:" + method);
        } return retVal; } finally {if

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.