博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java查看动态代理生成的代码
阅读量:5337 次
发布时间:2019-06-15

本文共 26273 字,大约阅读时间需要 87 分钟。

Java查看动态代理生成的代码

1.创建一个导出生成类的agent

agent是一个用来个jvm打交道的东西,需要实现一个静态的public static void premain(String agentArgs, Instrumentation inst) 方法.我使用如下的代码创建agent

package ctgu.jagent;import java.io.File;import java.io.FileOutputStream;import java.lang.instrument.ClassFileTransformer;import java.lang.instrument.IllegalClassFormatException;import java.lang.instrument.Instrumentation;import java.security.ProtectionDomain;public class CustomAgent implements ClassFileTransformer {     public static void premain(String agentArgs, Instrumentation inst) {        inst.addTransformer(new CustomAgent());    }    @Override    public byte[] transform(ClassLoader loader, String className, Class
classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (!className.startsWith("java") && !className.startsWith("sun")) { // 既不是java也不是sun开头的 // 导出代码 int lastIndexOf = className.lastIndexOf("/") + 1; String fileName = className.substring(lastIndexOf) + ".class"; exportClazzToFile("E:/javaeeworkspace/bytecode/exported/", fileName, classfileBuffer); System.out.println(className + " --> EXPORTED Succeess!"); } return classfileBuffer; } /** * * @param dirPath *目录以/结尾,且必须存在 * @param fileName * @param data */ private void exportClazzToFile(String dirPath, String fileName, byte[] data) { try { File file = new File(dirPath + fileName); if (!file.exists()) { file.createNewFile(); } FileOutputStream fos = new FileOutputStream(file); fos.write(data); fos.close(); } catch (Exception e) { System.out.println("exception occured while doing some file operation"); e.printStackTrace(); } }}

然后使用eclipse的导出功能导出jar(注意agent必须是jar的形式存在),在向导中使用指定的MANIFEST.MF文件,MANIFEST.MF文件的内容如下

Manifest-Version: 1.0Premain-Class: ctgu.jagent.CustomAgent

注意,这个premain-Class就是带有premain静态方法的类。

如果你使用maven,也可以用如下plugin

org.apache.maven.plugins
maven-jar-plugin
src/main/resources/META-INF/MANIFEST.MF

把manifestFile换成你存放自定义MANIFEST.MF的路径,然后mvn package就可以了。

导出的jar包这里假设叫jagent.jar

2. 使用jagent.jar

把jagent.jar放到工程下,运行的时候加上jvm参数

-javaagent:jagent.jar

注意:左右都没有空格,要是jvm提示找不到的话,可以用eclispe把jagent.jar加入到buildpath中。

3. 使用动态代理

3.0 原始目标的接口与实现

接口定义如下:

package ctgu.bytecode.proxy.service;public interface HelloService { public String sayHello(String name) ;}

实现如下:

package ctgu.bytecode.proxy.service.impl;    import ctgu.bytecode.proxy.service.HelloService;    public class HelloServiceImpl implements HelloService{        @Override    public String sayHello(String name) {        return "Hello "+name;    }       }

3.1 使用jdk的代理

private static void javaDynamicProxy() {    HelloService helloService=new HelloServiceImpl();    MyInvocationHandler handler=new MyInvocationHandler(helloService);        HelloService proxy = (HelloService)Proxy.newProxyInstance(HelloService.class.getClassLoader(),             new Class
[]{HelloService.class}, handler); String sayHello = proxy.sayHello("woober"); System.out.println(sayHello);}

其中MyInvocationHandler的代码如下:

package ctgu.bytecode.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class MyInvocationHandler implements InvocationHandler {    Object trueTarget;        public MyInvocationHandler(Object target) {        this.trueTarget=target;    }        @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("before invoke method:"+method.getName());        Object result = method.invoke(trueTarget, args);        System.out.println("invoke finish return:"+result);        return result;    }}

运行后输出:

ctgu/bytecode/TestMain --> EXPORTED Succeess!    ctgu/bytecode/proxy/service/impl/HelloServiceImpl --> EXPORTED Succeess!ctgu/bytecode/proxy/service/HelloService --> EXPORTED Succeess!ctgu/bytecode/proxy/MyInvocationHandler --> EXPORTED Succeess!com/sun/proxy/$Proxy0 --> EXPORTED Succeess!before invoke method:sayHelloinvoke finish return:Hello wooberHello woober

在第4部分会分析生成com/sun/proxy/$Proxy0的反编译代码。

3.2 使用cglib代理

private static void cgLibProxy(){           HelloService helloService=new HelloServiceImpl();    MyMethodIntercepter intercepter=new MyMethodIntercepter(helloService);           HelloService proxy = (HelloService)Enhancer.create(HelloService.class,intercepter);    System.err.println("Proxy class name is "+proxy.getClass().getName());    System.out.println(proxy.sayHello("Woober"));}

其中MyMethodIntercepter代码如下:

package ctgu.bytecode.proxy;import java.lang.reflect.Method;    import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class MyMethodIntercepter  implements MethodInterceptor{    Object trueTarget;        public MyMethodIntercepter(Object target) {         trueTarget=target;    }    @Override    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {        System.out.println("In cglib before invoke");        //这个methodProxy 是目标方法的一个代理,下面可以看出来                    Object result = proxy.invoke(trueTarget, args);        System.out.println("In cglib after invoke");        return result;    }}

运行输出:

ctgu/bytecode/TestMain --> EXPORTED Succeess!net/sf/cglib/proxy/Callback --> EXPORTED Succeess!ctgu/bytecode/proxy/service/impl/HelloServiceImpl --> EXPORTED Succeess!ctgu/bytecode/proxy/service/HelloService --> EXPORTED Succeess!ctgu/bytecode/proxy/MyMethodIntercepter --> EXPORTED Succeess!net/sf/cglib/proxy/MethodInterceptor --> EXPORTED Succeess!net/sf/cglib/proxy/Enhancer --> EXPORTED Succeess!中间省略大量cglib的类还有asm的类.....  ctgu/bytecode/proxy/service/HelloService$$EnhancerByCGLIB$$1af19a1d --> EXPORTED Succeess!net/sf/cglib/proxy/MethodProxy --> EXPORTED Succeess!net/sf/cglib/proxy/MethodProxy$CreateInfo --> EXPORTED Succeess!In cglib before invokeProxy class name is ctgu.bytecode.proxy.service.HelloService$$EnhancerByCGLIB$$1af19a1d省略大量cglib的类...ctgu/bytecode/proxy/service/HelloService$$FastClassByCGLIB$$c2826506 --> EXPORTED Succeess!ctgu/bytecode/proxy/service/HelloService$$EnhancerByCGLIB$$1af19a1d$$FastClassByCGLIB$$a45a31f6 --> EXPORTED Succeess!In cglib after invokeHello Woober

注意这两句话的顺序

In cglib before invokeProxy class name is ctgu.bytecode.proxy.service.HelloService$$EnhancerByCGLIB$$1af19a1d

按理说后面应该在后面这句应该在前面的,因为我使用system.err打的Proxy class name is这一句,跟out不是同一个流,所以以顺序不对(因为err会在eclipse里面标红,比较好看...)

下面重点关注ctgu.bytecode.proxy.service.HelloService$$EnhancerByCGLIB$$1af19a1d这个类

4. 查看生成类的源码

找一个顺手的反编译器,我用的是Bytecode Viewer ,github地址https://github.com/Konloch/bytecode-viewer

4.1 JDK动态代理反编译

/* * Decompiled with CFR 0_110. *  * Could not load the following classes: *  com.sun.proxy.$Proxy0 *  ctgu.bytecode.proxy.service.HelloService */package com.sun.proxy;import ctgu.bytecode.proxy.service.HelloService;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;public final class $Proxy0extends Proxyimplements HelloService {    private static Method m1;    private static Method m3;    private static Method m2;    private static Method m0;    public $Proxy0(InvocationHandler invocationHandler) {        super(invocationHandler);    }    public final boolean equals(Object object) {        try {            return (Boolean)this.h.invoke((Object)this, m1, new Object[]{object});        }        catch (Error | RuntimeException v0) {            throw v0;        }        catch (Throwable var2_2) {            throw new UndeclaredThrowableException(var2_2);        }    }    public final String sayHello(String string) {        try {            return (String)this.h.invoke((Object)this, m3, new Object[]{string});        }        catch (Error | RuntimeException v0) {            throw v0;        }        catch (Throwable var2_2) {            throw new UndeclaredThrowableException(var2_2);        }    }    public final String toString() {        try {            return (String)this.h.invoke((Object)this, m2, null);        }        catch (Error | RuntimeException v0) {            throw v0;        }        catch (Throwable var1_1) {            throw new UndeclaredThrowableException(var1_1);        }    }    public final int hashCode() {        try {            return (Integer)this.h.invoke((Object)this, m0, null);        }        catch (Error | RuntimeException v0) {            throw v0;        }        catch (Throwable var1_1) {            throw new UndeclaredThrowableException(var1_1);        }    }    static {        try {            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));            m3 = Class.forName("ctgu.bytecode.proxy.service.HelloService").getMethod("sayHello", Class.forName("java.lang.String"));            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);            return;        }        catch (NoSuchMethodException var1) {            throw new NoSuchMethodError(var1.getMessage());        }        catch (ClassNotFoundException var1_1) {            throw new NoClassDefFoundError(var1_1.getMessage());        }    }}

可以看出来他实现了HelloService接口,实现了sayHello方法,实际调用的时候是使用的invocationHandler并且传入了m3,m3实际就是靠反射拿到的接口中的sayHello方法。

m3 = Class.forName("ctgu.bytecode.proxy.service.HelloService").getMethod("sayHello", Class.forName("java.lang.String"));

4.2 CGLIB动态代理反编译

package ctgu.bytecode.proxy.service;import java.lang.reflect.*;import net.sf.cglib.proxy.*;import net.sf.cglib.core.*;public class HelloService$$EnhancerByCGLIB$$1af19a1d implements HelloService, Factory{    private boolean CGLIB$BOUND;    private static final ThreadLocal CGLIB$THREAD_CALLBACKS;    private static final Callback[] CGLIB$STATIC_CALLBACKS;    private MethodInterceptor CGLIB$CALLBACK_0;    private static final Method CGLIB$finalize$0$Method;    private static final MethodProxy CGLIB$finalize$0$Proxy;    private static final Object[] CGLIB$emptyArgs;    private static final Method CGLIB$equals$1$Method;    private static final MethodProxy CGLIB$equals$1$Proxy;    private static final Method CGLIB$toString$2$Method;    private static final MethodProxy CGLIB$toString$2$Proxy;    private static final Method CGLIB$hashCode$3$Method;    private static final MethodProxy CGLIB$hashCode$3$Proxy;    private static final Method CGLIB$clone$4$Method;    private static final MethodProxy CGLIB$clone$4$Proxy;    private static final Method CGLIB$sayHello$5$Method;    private static final MethodProxy CGLIB$sayHello$5$Proxy;        static void CGLIB$STATICHOOK1() {        CGLIB$THREAD_CALLBACKS = new ThreadLocal();        CGLIB$emptyArgs = new Object[0];        final Class
forName = Class.forName("ctgu.bytecode.proxy.service.HelloService$$EnhancerByCGLIB$$1af19a1d"); final Class
forName2; final Method[] methods = ReflectUtils.findMethods(new String[] { "finalize", "()V", "equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;" }, (forName2 = Class.forName("java.lang.Object")).getDeclaredMethods()); CGLIB$finalize$0$Method = methods[0]; CGLIB$finalize$0$Proxy = MethodProxy.create((Class)forName2, (Class)forName, "()V", "finalize", "CGLIB$finalize$0"); CGLIB$equals$1$Method = methods[1]; CGLIB$equals$1$Proxy = MethodProxy.create((Class)forName2, (Class)forName, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1"); CGLIB$toString$2$Method = methods[2]; CGLIB$toString$2$Proxy = MethodProxy.create((Class)forName2, (Class)forName, "()Ljava/lang/String;", "toString", "CGLIB$toString$2"); CGLIB$hashCode$3$Method = methods[3]; CGLIB$hashCode$3$Proxy = MethodProxy.create((Class)forName2, (Class)forName, "()I", "hashCode", "CGLIB$hashCode$3"); CGLIB$clone$4$Method = methods[4]; CGLIB$clone$4$Proxy = MethodProxy.create((Class)forName2, (Class)forName, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4"); final Class
forName3; CGLIB$sayHello$5$Method = ReflectUtils.findMethods(new String[] { "sayHello", "(Ljava/lang/String;)Ljava/lang/String;" }, (forName3 = Class.forName("ctgu.bytecode.proxy.service.HelloService")).getDeclaredMethods())[0]; CGLIB$sayHello$5$Proxy = MethodProxy.create((Class)forName3, (Class)forName, "(Ljava/lang/String;)Ljava/lang/String;", "sayHello", "CGLIB$sayHello$5"); } final void CGLIB$finalize$0() throws Throwable { super.finalize(); } protected final void finalize() throws Throwable { MethodInterceptor cglib$CALLBACK_2; MethodInterceptor cglib$CALLBACK_0; if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) == null) { CGLIB$BIND_CALLBACKS(this); cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0); } if (cglib$CALLBACK_0 != null) { cglib$CALLBACK_2.intercept((Object)this, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$finalize$0$Method, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$emptyArgs, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$finalize$0$Proxy); return; } super.finalize(); } final boolean CGLIB$equals$1(final Object o) { return super.equals(o); } public final boolean equals(final Object o) { MethodInterceptor cglib$CALLBACK_2; MethodInterceptor cglib$CALLBACK_0; if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) == null) { CGLIB$BIND_CALLBACKS(this); cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0); } if (cglib$CALLBACK_0 != null) { final Object intercept = cglib$CALLBACK_2.intercept((Object)this, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$equals$1$Method, new Object[] { o }, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$equals$1$Proxy); return intercept != null && (boolean)intercept; } return super.equals(o); } final String CGLIB$toString$2() { return super.toString(); } public final String toString() { MethodInterceptor cglib$CALLBACK_2; MethodInterceptor cglib$CALLBACK_0; if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) == null) { CGLIB$BIND_CALLBACKS(this); cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0); } if (cglib$CALLBACK_0 != null) { return (String)cglib$CALLBACK_2.intercept((Object)this, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$toString$2$Method, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$emptyArgs, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$toString$2$Proxy); } return super.toString(); } final int CGLIB$hashCode$3() { return super.hashCode(); } public final int hashCode() { MethodInterceptor cglib$CALLBACK_2; MethodInterceptor cglib$CALLBACK_0; if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) == null) { CGLIB$BIND_CALLBACKS(this); cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0); } if (cglib$CALLBACK_0 != null) { final Object intercept = cglib$CALLBACK_2.intercept((Object)this, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$hashCode$3$Method, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$emptyArgs, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$hashCode$3$Proxy); return (intercept == null) ? 0 : ((Number)intercept).intValue(); } return super.hashCode(); } final Object CGLIB$clone$4() throws CloneNotSupportedException { return super.clone(); } protected final Object clone() throws CloneNotSupportedException { MethodInterceptor cglib$CALLBACK_2; MethodInterceptor cglib$CALLBACK_0; if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) == null) { CGLIB$BIND_CALLBACKS(this); cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0); } if (cglib$CALLBACK_0 != null) { return cglib$CALLBACK_2.intercept((Object)this, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$clone$4$Method, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$emptyArgs, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$clone$4$Proxy); } return super.clone(); } final String CGLIB$sayHello$5(final String s) { return super.sayHello(s); } public final String sayHello(final String s) { MethodInterceptor cglib$CALLBACK_2; MethodInterceptor cglib$CALLBACK_0; if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) == null) { CGLIB$BIND_CALLBACKS(this); cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0); } if (cglib$CALLBACK_0 != null) { return (String)cglib$CALLBACK_2.intercept((Object)this, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$sayHello$5$Method, new Object[] { s }, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$sayHello$5$Proxy); } return super.sayHello(s); } public static MethodProxy CGLIB$findMethodProxy(final Signature signature) { final String string = signature.toString(); switch (string.hashCode()) { case -1816210712: { if (string.equals("sayHello(Ljava/lang/String;)Ljava/lang/String;")) { return HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$sayHello$5$Proxy; } break; } case -1574182249: { if (string.equals("finalize()V")) { return HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$finalize$0$Proxy; } break; } case -508378822: { if (string.equals("clone()Ljava/lang/Object;")) { return HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$clone$4$Proxy; } break; } case 1826985398: { if (string.equals("equals(Ljava/lang/Object;)Z")) { return HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$equals$1$Proxy; } break; } case 1913648695: { if (string.equals("toString()Ljava/lang/String;")) { return HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$toString$2$Proxy; } break; } case 1984935277: { if (string.equals("hashCode()I")) { return HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$hashCode$3$Proxy; } break; } } return null; } public HelloService$$EnhancerByCGLIB$$1af19a1d() { CGLIB$BIND_CALLBACKS(this); } public static void CGLIB$SET_THREAD_CALLBACKS(final Callback[] array) { HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$THREAD_CALLBACKS.set(array); } public static void CGLIB$SET_STATIC_CALLBACKS(final Callback[] cglib$STATIC_CALLBACKS) { CGLIB$STATIC_CALLBACKS = cglib$STATIC_CALLBACKS; } private static final void CGLIB$BIND_CALLBACKS(final Object o) { final HelloService$$EnhancerByCGLIB$$1af19a1d helloService$$EnhancerByCGLIB$$1af19a1d = (HelloService$$EnhancerByCGLIB$$1af19a1d)o; if (!helloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$BOUND) { helloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$BOUND = true; Object o2; if ((o2 = HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$THREAD_CALLBACKS.get()) != null || (o2 = HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$STATIC_CALLBACKS) != null) { helloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])o2)[0]; } } } public Object newInstance(final Callback[] array) { CGLIB$SET_THREAD_CALLBACKS(array); final HelloService$$EnhancerByCGLIB$$1af19a1d helloService$$EnhancerByCGLIB$$1af19a1d = new HelloService$$EnhancerByCGLIB$$1af19a1d(); CGLIB$SET_THREAD_CALLBACKS(null); return helloService$$EnhancerByCGLIB$$1af19a1d; } public Object newInstance(final Callback callback) { CGLIB$SET_THREAD_CALLBACKS(new Callback[] { callback }); final HelloService$$EnhancerByCGLIB$$1af19a1d helloService$$EnhancerByCGLIB$$1af19a1d = new HelloService$$EnhancerByCGLIB$$1af19a1d(); CGLIB$SET_THREAD_CALLBACKS(null); return helloService$$EnhancerByCGLIB$$1af19a1d; } public Object newInstance(final Class[] array, final Object[] array2, final Callback[] array3) { CGLIB$SET_THREAD_CALLBACKS(array3); switch (array.length) { case 0: { final HelloService$$EnhancerByCGLIB$$1af19a1d helloService$$EnhancerByCGLIB$$1af19a1d = new HelloService$$EnhancerByCGLIB$$1af19a1d(); CGLIB$SET_THREAD_CALLBACKS(null); return helloService$$EnhancerByCGLIB$$1af19a1d; } default: { throw new IllegalArgumentException("Constructor not found"); } } } public Callback getCallback(final int n) { CGLIB$BIND_CALLBACKS(this); Object cglib$CALLBACK_0 = null; switch (n) { case 0: { cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0; break; } default: { cglib$CALLBACK_0 = null; break; } } return (Callback)cglib$CALLBACK_0; } public void setCallback(final int n, final Callback callback) { switch (n) { case 0: { this.CGLIB$CALLBACK_0 = (MethodInterceptor)callback; break; } } } public Callback[] getCallbacks() { CGLIB$BIND_CALLBACKS(this); return new Callback[] { this.CGLIB$CALLBACK_0 }; } public void setCallbacks(final Callback[] array) { this.CGLIB$CALLBACK_0 = (MethodInterceptor)array[0]; } static { CGLIB$STATICHOOK1(); }}

生成的类同样实现了 HelloService接口并且实现了Factory接口,Factory接口如下:

public interface Factory {        Object newInstance(Callback callback);               Object newInstance(Callback[] callbacks);           Object newInstance(Class[] types, Object[] args, Callback[] callbacks);        Callback getCallback(int index);     void setCallback(int index, Callback callback);         void setCallbacks(Callback[] callbacks);             Callback[] getCallbacks();}

直接看生成的sayHello实现

public final String sayHello(final String s) {        MethodInterceptor cglib$CALLBACK_2;        MethodInterceptor cglib$CALLBACK_0;        if ((cglib$CALLBACK_0 = (cglib$CALLBACK_2 = this.CGLIB$CALLBACK_0)) == null) {            CGLIB$BIND_CALLBACKS(this);            cglib$CALLBACK_2 = (cglib$CALLBACK_0 = this.CGLIB$CALLBACK_0);        }        if (cglib$CALLBACK_0 != null) {            return (String)cglib$CALLBACK_2.intercept((Object)this, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$sayHello$5$Method, new Object[] { s }, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$sayHello$5$Proxy);        }        return super.sayHello(s);    }

可以看到cglib$CALLBACK_0是通过CGLIB$BIND_CALLBACKS(this)完成的,glib$CALLBACK_2跟glib$CALLBACK_2是一个东西。

再看CGLIB$BIND_CALLBACKS(this)做了啥

private static final void CGLIB$BIND_CALLBACKS(final Object o) {    final HelloService$$EnhancerByCGLIB$$1af19a1d helloService$$EnhancerByCGLIB$$1af19a1d = (HelloService$$EnhancerByCGLIB$$1af19a1d)o;    if (!helloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$BOUND) {        helloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$BOUND = true;        Object o2;        if ((o2 = HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$THREAD_CALLBACKS.get()) != null || (o2 = HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$STATIC_CALLBACKS) != null) {            helloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])o2)[0];        }    }}

CGLIB$CALLBACK_0是CGLIB$THREAD_CALLBACKS.get()或者CGLIB$STATIC_CALLBACKS,

CGLIB$THREAD_CALLBACKS是一个threadlocal的成员变量。

CGLIB$THREAD_CALLBACKS是由下面的CGLIB$SET_THREAD_CALLBACKS方法来设置的,

public static void CGLIB$SET_THREAD_CALLBACKS(final Callback[] array) {    HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$THREAD_CALLBACKS.set(array);}

这个方法被Factory接口的newInstance调用

public Object newInstance(final Callback[] array) {    CGLIB$SET_THREAD_CALLBACKS(array);    final HelloService$$EnhancerByCGLIB$$1af19a1d helloService$$EnhancerByCGLIB$$1af19a1d = new HelloService$$EnhancerByCGLIB$$1af19a1d();    CGLIB$SET_THREAD_CALLBACKS(null);    return helloService$$EnhancerByCGLIB$$1af19a1d;}public Object newInstance(final Callback callback) {    CGLIB$SET_THREAD_CALLBACKS(new Callback[] { callback });    final HelloService$$EnhancerByCGLIB$$1af19a1d helloService$$EnhancerByCGLIB$$1af19a1d = new HelloService$$EnhancerByCGLIB$$1af19a1d();    CGLIB$SET_THREAD_CALLBACKS(null);    return helloService$$EnhancerByCGLIB$$1af19a1d;}

我看不懂的就是他为什么 CGLIB$SET_THREAD_CALLBACKS(array); 之后又 CGLIB$SET_THREAD_CALLBACKS(null); ???反编译的问题?

对于CGLIB$STATIC_CALLBACKS是由

public static void CGLIB$SET_STATIC_CALLBACKS(final Callback[] cglib$STATIC_CALLBACKS) {    CGLIB$STATIC_CALLBACKS = cglib$STATIC_CALLBACKS;}

这个方法赋值上的,但是我没找到调用的地方。

最后看实际上执行的方法的地方,就是掉的intercepter的intercept方法。

(String)cglib$CALLBACK_2.intercept((Object)this, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$sayHello$5$Method, new Object[] { s }, HelloService$$EnhancerByCGLIB$$1af19a1d.CGLIB$sayHello$5$Proxy);

最后一个参数是个MethodProxy

CGLIB$sayHello$5$Proxy = MethodProxy.create((Class)forName3, (Class)forName, "(Ljava/lang/String;)Ljava/lang/String;", "sayHello", "CGLIB$sayHello$5");

我猜应该是对方法生成了一个代理

final String CGLIB$sayHello$5(final String s) {    return super.sayHello(s);}

关于这个cglib生成的字节码好多反编译工具都不能解析。不保证上面生成代码的正确性

转载于:https://www.cnblogs.com/ctgulong/p/5011614.html

你可能感兴趣的文章
字母和数字键的键码值(keyCode)
查看>>
协议和代理
查看>>
IE8调用window.open导出EXCEL文件题目
查看>>
sql server 2008 不允许保存更改,您所做的更改要求删除并重新创建以下表 的解决办法(转)...
查看>>
[转]iOS学习笔记(2)--Xcode6.1创建仅xib文件无storyboard的hello world应用
查看>>
Spring mvc初学
查看>>
有意思的代码片段
查看>>
C8051开发环境
查看>>
VTKMY 3.3 VS 2010 Configuration 配置
查看>>
255. Verify Preorder Sequence in Binary Search Tree
查看>>
01_1_准备ibatis环境
查看>>
windows中修改catalina.sh上传到linux执行报错This file is needed to run this program解决
查看>>
[fowarding]Ubuntu jsp平台使用JDBC来连接MySQL数据库
查看>>
JavaScript中的BOM和DOM
查看>>
360浏览器兼容模式 不能$.post (不是a 连接 onclick的问题!!)
查看>>
Yii安装使用教程(转)
查看>>
Java四种引用包括强引用,软引用,弱引用,虚引用。
查看>>
spring注入Properties
查看>>
微信小程序开发之从相册获取图片 使用相机拍照 本地图片上传
查看>>
【BZOJ-2295】我爱你啊 暴力
查看>>