It is not necessary to pass the ClassLoader as a parameter before using Cglib, but the dynamic agent wants to enter this method with this doubt:
Proxy.newproxyinstance (ClassLoader, interfaces, Invocationhandler)
In ClassLoader to find interfaces, if also loaded in order to continue to execute, and with Proxygenerator dynamically generated a proxy class bytecode file (using the cache technology, only need to generate once), and then use ClassLoader this bytecode file in. This is the role of ClassLoader.
You can see the resulting bytecode class in this way.
Add execution Parameters:
System.setproperty ("Sun.misc.ProxyGenerator.saveGeneratedFiles", "true")
The resulting bytecode file will be preserved and compiled as follows:
Package Demo;import Java.lang.reflect.invocationhandler;import Java.lang.reflect.method;import Java.lang.reflect.proxy;import java.lang.reflect.undeclaredthrowableexception;public Final class $Proxy 0 extends Proxy implements IA {private static Method M1; private static Method M4; private static Method m3; private static Method M0; private static Method m2; Public $Proxy 0 (Invocationhandler paraminvocationhandler) {super (Paraminvocationhandler); The public final Boolean equals (Object paramobject) {try {return (Boolean) This.h.invoke (this, M1, new Object[] {paramobject}). Booleanvalue (); } catch (RuntimeException localruntimeexception) {throw localruntimeexception; } catch (Throwable localthrowable) {throw new undeclaredthrowableexception (localthrowable); }} public final int B (String paramstring) {try {return (Integer) This.h.invoke (this, M4, new OBJEC T[] {paramstring}). Intvalue (); } catch (RuntimeexceptiOn localruntimeexception) {throw localruntimeexception; } catch (Throwable localthrowable) {throw new undeclaredthrowableexception (localthrowable); }} public final void a () {try {This.h.invoke (this, M3, null); Return } catch (RuntimeException localruntimeexception) {throw localruntimeexception; } catch (Throwable localthrowable) {throw new undeclaredthrowableexception (localthrowable); }} public final int hashcode () {try {return ((Integer) This.h.invoke (this, M0, null)). Intvalue (); } catch (RuntimeException localruntimeexception) {throw localruntimeexception; } catch (Throwable localthrowable) {throw new undeclaredthrowableexception (localthrowable); }} public final String toString () {try {return (String) This.h.invoke (this, M2, null); } catch (RuntimeException localruntimeexception) {throw localruntimeexception; } catch (Throwable localthrowable) {throw new UndeclarEdthrowableexception (localthrowable); }} static {try {m1 = Class.forName ("Java.lang.Object"). GetMethod ("equals", new class[] {Class.forna Me ("Java.lang.Object")}); M4 = Class.forName ("Demo. IA "). GetMethod (" B ", new class[] {class.forname (" java.lang.String ")}); M3 = Class.forName ("Demo. IA "). GetMethod (" A ", new class[0]); M0 = Class.forName ("Java.lang.Object"). GetMethod ("Hashcode", new Class[0]); M2 = Class.forName ("Java.lang.Object"). GetMethod ("ToString", new Class[0]); } catch (Nosuchmethodexception localnosuchmethodexception) {throw new Nosuchmethoderror (LOCALNOSUCHMETHODEXCEPTION.G Etmessage ()); } catch (ClassNotFoundException localclassnotfoundexception) {throw new Noclassdeffounderror (LOCALCLASSNOTFOUNDEXCEP Tion.getmessage ()); } }}
It can be found that all the implementations of the interface methods are delegated to the Invocationhandler invoke method, which is where the proxy mode is implemented.
--------------------------------------------------------------------------
Cglib do not need to pass in the ClassLoader, the code will find their own context of the ClassLoader, this design so that less than a classloader this very rare parameter for beginners to use to simple point.
You can set System.setproperty (Debuggingclasswriter.debug_location_property, "Byte code file save location" to save the dynamic bytecode generated by Cglib.
Single-cell analysis of generated bytecode
The dynamically generated inheritance class overwrites all the methods of the parent class we use, intercepting it and handing it over to the set of Methodinterceptor to execute.
public object intercept (object obj, Method method, object[] args,
Methodproxy proxy)
The first parameter, obj, is a dynamically generated subclass. The second parameter is the method of the original class.
We generally use the Proxy.invokesuper (Obj,args) method. This is a good understanding of how the original class is executed. There is also a method Proxy.invoke (Obj,args), which is the method that executes the generated subclass. If the incoming obj is a subclass, a memory overflow occurs because the subclass's method does not quite go into the Intercept method, and this method calls the subclass method, and two methods are called directly.
Let's look at Methodproxy, each method in the primitive class has a corresponding methodproxy in the dynamic subclass, and a methodproxy corresponds to two dynamically generated Fastclass classes, one corresponding to the original method, one corresponding to the newly generated subclass, Methodproxy.invokesuper is handed over to the original method that Fastclass,methodproxy.invoke to another.
These 2 extra-generated classes function when we call a method, not by reflection, but rather by locating the method in a way similar to an array subscript, directly executing the class method.
The code generated by Fastclass is similar to this
Public Object Invoke (int paramint, Object paramobject, object[] paramarrayofobject) throws InvocationTargetException { //Byte code: 0:aload_2 1:checkcast 159net/sf/cglib/mytest/a$$ enhancerbycglib$ $f 84d7df 4:iload_1 //paramint parameters in Stack 5:tableswitchdefault:+403, 408 136 ...//through Paramint is also equivalent to the array of small flags, to locate the code snippet executed by the method .... 148:aload_3 149:iconst_0 150:aaload 151:invokevirtual 166net/sf/cglib/mytest/a$ $EnhancerByCGLIB $$ F84d7df:equals (ljava/lang/object;) Z//Direct quick execution method ...}}
Http://www.cnblogs.com/onlywujun/p/3524690.html
JDK and Cglib simple comprehension (go)