SPRINGAOP-JDK Dynamic agent and CGLIB agent

Source: Internet
Author: User
Tags reflection throwable

In Spring, the AOP proxy is implemented using the JDK dynamic agent and the CGLIB proxy, and by default if the target object is an interface, the JDK dynamic agent is used, otherwise CGLIB is used to generate the proxy class. 1.JDK Dynamic Agent

Then the interface (Userservicebo), target object (Proxied object Userserviceimpl), proxy object ( $Proxy0 ) Three specific relationships can be used to represent:

As you know, the JDK dynamic agent is the agent of the interface, the proxy class implements the interface, and inherits the proxy class, and the target object is not directly related to the surrogate object, except that they all implement the interface, and the proxy object executes the method when the internal end is the delegate target object execution concrete method.

Examples are as follows:

The JDK proxy is the agent for the interface, so first write an interface class:

 Public Interface UserService {    public  int  Add ();}

The interface is then implemented as follows:

 Public class Userserviceimpl implements UserService {    @Override    publicint  Add () {        System. out. println (" Execute Add method ");         return 0 ;    }}

The JDK dynamic agent is required to implement the Invocationhandler interface, so create a Invocationhandler implementation class:

 Public classMyinvocationhandler implements Invocationhandler {PrivateObject Target;  PublicMyinvocationhandler (Object target) {super ();  This. target =Target; } @Override Publicobject Invoke (Object proxy, Method method, object[] args) throws Throwable {//1System. out. println ("********begin"+method.getname () +"********"); //2Object result =Method.invoke (target, args); //3System. out. println ("********end"+method.getname () +"*********"); returnresult; }     PublicObject GetProxy () {//4        returnProxy.newproxyinstance (Thread.CurrentThread (). Getcontextclassloader (), Target.getclass (). GetInterfaces (), This); }}

Next, test the code as follows:

 Public Static voidMain (string[] args) {//5To Open this switch, you can save the generated proxy class to diskSystem.getproperties (). Put ("Sun.misc.ProxyGenerator.saveGeneratedFiles","true"); //6 Creating the target object (the object being proxied)UserService Service =NewUserserviceimpl (); //7 Create an Invocationhandler instance and pass the Proxied objectMyinvocationhandler handler =NewMyinvocationhandler (service); //8 Generating proxy classesUserService proxy =(UserService) handler.getproxy (); Proxy.add ();}

where code 6 Creates an Userserviceimpl instance object, which is the target object to be proxied.

Code 7 creates an Invocationhandler instance and passes the proxy target object service to the internal variable target.

Code 8 calls Myinvocationhandler's GetProxy method to generate a proxy object using the JDK.

Code 5 Sets the System attribute variable Sun.misc.ProxyGenerator.saveGeneratedFiles to True, which is to allow code (8) to generate a byte-code file for the proxy object to be saved to disk.

Then we do the anti-compilation look at the core code, run after the project will be generated under the Com.sun.proxy $Proxy 0.class class, after the post-compilation core Java code is as follows:

Package Com.sun.proxy;import Java.lang.reflect.invocationhandler;import java.lang.reflect.method;import Java.lang.reflect.proxy;import Java.lang.reflect.undeclaredthrowableexception;import Proxy. Jdk. Userservicebo; PublicFinalclass$Proxy 0 extends Proxy implements userservice{Private StaticMethod M1; Private StaticMethod m3; Private StaticMethod M0; Private StaticMethod m2;  Public$Proxy 0 (Invocationhandler paraminvocationhandler) {super (Paraminvocationhandler); }   PublicFinalintAdd () {Try    {    //9The first argument is the proxy class itself, the second is the method of implementing the class, and the third is the parameter      returnH.invoke ( This, M3,NULL); }    Catch(error|runtimeexception Localerror) {      ThrowLocalerror; }    Catch(Throwable localthrowable) {Throw Newundeclaredthrowableexception (localthrowable); }  } ... OmittedStatic  {    Try{m3= Class.forName ("Proxy. Jdk. UserService"). GetMethod ("Add",Newclass[0]); ... Omittedreturn; }    Catch(nosuchmethodexception localnosuchmethodexception) ... omitted}}

You can see that the $Proxy0 h in code 9 in the proxy class is an instance of the Myinvocationhandler created inside the main function, H.invoke (this, M3, null) is actually called Myinvocationha Ndler's Invoke method,

The latter is delegated to the object to be executed, where the target object method can be intercepted, and then its function is enhanced. In addition, the code 8 generated proxy object is actually $Proxy0 an instance, when called Proxy.add (),

is actually called the proxy class $Proxy0 of the Add method, the latter is delegated to the Myinvocationhandler invoke method, the Invoke method inside has called the target object service's Add method.

Therefore, the JDK dynamic agent mechanism is summarized as follows:

The JDK dynamic agent mechanism can only proxy the interface, its principle is to dynamically generate a proxy class, the proxy class implements the interface of the target object, the target object and the proxy class are implemented interface, but the target object and the proxy class object is not the same, so the two can not be assigned to each other.

CGLIB Dynamic Agent

CGLIB is the proxy for the implementation class compared to the JDK dynamic proxy, which means that the CGLIB can be used for proxies regardless of whether the target object has an interface.

Then the interface (Userservicebo), the target object (the Proxied object Userserviceimpl), the proxy object ( UserServiceImpl$$EnhancerByCGLIB$$d0bce05a ) Three specific relationships can be used to represent:

The interface and the proxy object are not related, the proxy object inherits the target object and implements the Factory interface.

Examples are as follows:

Using CGLIB for proxying requires implementing Methodinterceptor, creating a Method Interceptor Cglibproxy class:

 Public classCglibproxy implements Methodinterceptor {//Ten    PrivateEnhancer enhancer =Newenhancer (); // One     PublicObject getproxy (Class clazz) {//12 Setting the class object for the proxy classesEnhancer.setsuperclass (Clazz); //13 Setting Interceptor callbacksEnhancer.setcallback ( This); returnenhancer.create (); } @Override PublicObject Intercept (Object obj, Method method, object[] args, Methodproxy proxy) throws Throwable {SYSTEM. out. println (Obj.getclass (). GetName () +"."+method.getname ()); Object result=proxy.invokesuper (obj, args); returnresult; }}

The test classes are as follows:

 Public voidTestcglibproxy () {//14 generating proxy classes to localSystem.setproperty (Debuggingclasswriter.debug_location_property,"/users/zhuizhumengxiang/downloads"); //15 generating target objectsUserserviceimpl Service =NewUserserviceimpl (); //16 Creating a Cglibproxy objectCglibproxy CP =NewCglibproxy (); //17 Generating proxy classesUserservicebo proxy =(Userservicebo) Cp.getproxy (Service.getclass ()); Proxy.add ();}

Executing the code above will /Users/huangjuncong/Downloads generate the proxy class file in the directory UserServiceImpl$$EnhancerByCGLIB$$d0bce05a.class , and the post-compilation code is as follows:

 Public classuserserviceimpl$ $EnhancerByCGLIB $ $d 0bce05a extends Userserviceimpl implements factory{Static voidCglib$statichook1 () {//18 NULL ParametersCglib$emptyargs =Newobject[0]; //19 Get the list of add methods for Userserviceimplmethod[] tmp191_188 = Reflectutils.findmethods (NewString[] {"Add","() I"}, (LocalClass2 = Class.forName ("Zlx.cglib.zlx.UserServiceImpl") . Getdeclaredmethods ()); cglib$add$0$Method = tmp191_188[0]; //20 Create a cglib$add$0, according to create a methodproxycglib$add$0$Proxy = Methodproxy.create (LocalClass2, LocalClass1,"() I","Add","cglib$add$0"); }  Static{Cglib$statichook1 (); }  //(+)Finalintcglib$add$0()  {    returnSuper.add (); }  //(a)   PublicFinalintAdd () {... Omitted//23 Get the Interceptor, here is an example of CglibproxyMethodinterceptor tmp17_14 = This.    Cglib$callback_0; if(Tmp17_14! =NULL)    {
//24 intercept method for calling interceptorsObject tmp36_31 = tmp17_14.intercept ( This, cglib$add$0$Method, Cglib$emptyargs, cglib$add$0$Proxy); tmp36_31; returntmp36_31 = =NULL?0: (number) tmp36_31). Intvalue (); } returnSuper.add (); } }

The code has created one CGLIB$emptyArgs because the Add method is non-entry, so the number of object objects created here is 0, which is the third parameter of the Intercept of the Cglibproxy interceptor.

The code takes a list of Userserviceimpl's add methods and assigns the unique method to the CGLIB$add$0$Method Cglibproxy Interceptor's intercept second parameter.

The code creates a Methodproxy object that invokes the method of the proxy object directly when calling the Invokesuper method of the Methodproxy object, that is CGLIB$add$0 , calling the add of the parent class Userserviceimpl directly method, which avoids a reflection call, creates a Methodproxy object that is the fourth parameter of the intercept of the Cglibproxy interceptor.

code is the proxy class of the Add method, code (17) Generated proxy object is UserServiceImpl$$EnhancerByCGLIB$$d0bce05a an instance, when the call Proxy.add () method is called code (22), from the code (22) Know the internal call the Interceptor Cglibproxy The Intercept method, we know that the first parameter of intercept is the proxy object itself.

  So the Cglib agent is summarized as follows:

    CGLIB is the proxy for the target object itself, so whether the target object has an interface or not, the target object can be proxied by using the bytecode generation tool to generate a proxy class that inherits the target object in memory and then creates a proxy object instance.

Because the parent class of the proxy class is the target object, the proxy class can be assigned to the target object, and if the target object has an interface, the proxy object can also be assigned to the interface.

The bytecode of the proxy class generated in the CGLIB dynamic proxy is more complex than the JDK.

Overall :

The JDK invokes the method of the target class using the reflection mechanism, and CGLIB invokes the target class method directly using a similar index, so the JDK dynamic agent generates the proxy class faster than the CGLIB, but runs slower than CGLIB, and the JDK proxy can only proxy the target object with the interface.

SPRINGAOP-JDK Dynamic agent and CGLIB agent

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.