stone2083

CGlib简单介绍

CGlib概述:
cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。
cglib封装了asm,可以在运行期动态生成新的class。
cglib用于AOP,jdk中的proxy必须基于接口,cglib却没有这个限制。

CGlib应用:
以一个实例在简单介绍下cglib的应用。
我们模拟一个虚拟的场景,关于信息的管理。

1)原始需求是任何人可以操作信息的create,update,delete,query操作。
InfoManager.java--封装对信息的操作
public class InfoManager {
    
// 模拟查询操作
    public void query() {
        System.out.println(
"query");
    }
    
// 模拟创建操作
    public void create() {
        System.out.println(
"create");
    }
    
// 模拟更新操作
    public void update() {
        System.out.println(
"update");
    }
    
// 模拟删除操作
    public void delete() {
        System.out.println(
"delete");
    }
}
InfoManagerFactory.java--工厂类
public class InfoManagerFactory {
    
private static InfoManager manger = new InfoManager();
    
/**
     * 创建原始的InfoManager
     * 
     * 
@return
     
*/
    
public static InfoManager getInstance() {
        
return manger;
    }
}
client.java--供客户端调用
public class Client {

    
public static void main(String[] args) {
        Client c 
= new Client();
        c.anyonecanManager();
    }

    
/**
     * 模拟:没有任何权限要求,任何人都可以操作
     
*/
    
public void anyonecanManager() {
        System.out.println(
"any one can do manager");
        InfoManager manager 
= InfoManagerFactory.getInstance();
        doCRUD(manager);
        separatorLine();
    }

    
/**
     * 对Info做增加/更新/删除/查询操作
     * 
     * 
@param manager
     
*/
    
private void doCRUD(InfoManager manager) {
        manager.create();
        manager.update();
        manager.delete();
        manager.query();
    }

    
/**
     * 加一个分隔行,用于区分
     
*/
    
private void separatorLine() {
        System.out.println(
"################################");
    }

}
至此,没有涉及到cglib的内容,因为需求太简单了,但是接下来,需求发生了改变,要求:

2)只有一个叫“maurice”的用户登录,才允许对信息进行create,update,delete,query的操作。
怎么办?难道在每个方法前,都加上一个权限判断吗?这样重复逻辑太多了,于是乎想到了Proxy(代理模式),但是原先的InfoManager也没有实现接口,不能采用jdk的proxy。那么cglib在这边就要隆重登场。
一旦使用cgblig,只需要添加一个MethodInterceptor的类以及修改factory代码就可以实现这个需求。
AuthProxy.java--权限校验代理类
public class AuthProxy implements MethodInterceptor {

    
private String name; // 会员登录名

    
public AuthProxy(String name) {
        
this.name = name;
    }

    
/**
     * 权限校验,如果会员名为:maurice,则有权限做操作,否则提示没有权限
     
*/
    @Override
    
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        
if (!"maurice".equals(this.name)) {
            System.out.println(
"AuthProxy:you have no permits to do manager!");
            
return null;
        }
        
return proxy.invokeSuper(obj, args);
    }

    
public String getName() {
        
return name;
    }

    
public void setName(String name) {
        
this.name = name;
    }

}
InfoManagerFactory.java--代码变动如下:
public class InfoManagerFactory {

    
/**
     * 创建带有权限检验的InfoManager
     * 
     * 
@param auth
     * 
@return
     
*/
    
public static InfoManager getAuthInstance(AuthProxy auth) {
        Enhancer enhancer 
= new Enhancer();
        enhancer.setSuperclass(InfoManager.
class);
        enhancer.setCallback(auth);
        
return (InfoManager) enhancer.create();
    }

    
}
client.java--代码修改如下
public class Client {

    
public static void main(String[] args) {
        Client c 
= new Client();
        c.haveNoAuthManager();
        c.haveAuthManager();
    }

    
/**
     * 模拟:登录会员没有权限
     
*/
    
public void haveNoAuthManager() {
        System.out.println(
"the loginer's name is not maurice,so have no permits do manager");
        InfoManager noAuthManager 
= InfoManagerFactory.getAuthInstance(new AuthProxy("maurice1"));
        doCRUD(noAuthManager);
        separatorLine();
    }

    
/**
     * 模拟:登录会员有权限
     
*/
    
public void haveAuthManager() {
        System.out.println(
"the loginer's name is maurice,so have permits do manager");
        InfoManager authManager 
= InfoManagerFactory.getAuthInstance(new AuthProxy("maurice"));
        doCRUD(authManager);
        separatorLine();
    }

    
/**
     * 对Info做增加/更新/删除/查询操作
     * 
     * 
@param manager
     
*/
    
private void doCRUD(InfoManager manager) {
        manager.create();
        manager.update();
        manager.delete();
        manager.query();
    }

    
/**
     * 加一个分隔行,用于区分
     
*/
    
private void separatorLine() {
        System.out.println(
"################################");
    }

}
执行下代码,发现这时client端中已经加上了权限校验。
同样是InfoManager,为什么这时能多了权限的判断呢?Factory中enhancer.create()返回的到底是什么对象呢?这个疑问将在第三部分CGlib中解释。
这边的代码,其实是介绍了cglib中的enhancer功能.

到这里,参照上面的代码,就可以使用cglib带来的aop功能了。但是为了更多介绍下cglib的功能,模拟需求再次发生变化:

3)由于query功能用户maurice才能使用,招来其他用户的强烈的抱怨,所以权限再次变更,只有create,update,delete,才需要权限保护,query任何人都可以使用。
怎么办?采用AuthProxy,使得InfoManager中的所有方法都被代理,加上了权限的判断。当然,最容易想到的办法,就是在AuthProxy的intercept的方法中再做下判断,如果代理的method是query,不需要权限验证。这么做,可以,但是一旦逻辑比较复杂的时候,intercept这个方法要做的事情会很多,逻辑会异常的复杂。
幸好,cglib还提供了CallbackFilter。使用CallbackFilter,可以明确表明,被代理的类(InfoManager)中不同的方法,被哪个拦截器(interceptor)拦截。
AuthProxyFilter.java
public class AuthProxyFilter implements CallbackFilter {

    
private static final int AUTH_NEED     = 0;
    
private static final int AUTH_NOT_NEED = 1;

    
/**
     * <pre>
     * 选择使用的proxy
     * 如果调用query函数,则使用第二个proxy
     * 否则,使用第一个proxy
     * </pre>
     
*/
    @Override
    
public int accept(Method method) {
        
if ("query".equals(method.getName())) {
            
return AUTH_NOT_NEED;
        }
        
return AUTH_NEED;
    }

}
这段代码什么意思?其中的accept方法的意思是说,如果代理的方法是query(),那么使用第二个拦截器去拦截,如果代理的方法不是query(),那么使用第一个拦截器去拦截。所以我们只要再写一个拦截器,不做权限校验就行了。(其实,cglib中的NoOp.INSTANCE就是一个空的拦截器,只要配置上这个就可以了。)
InfoManagerFactory.java--代码修改如下:(配置不同的拦截器和filter)
public class InfoManagerFactory {

    
/**
     * 创建不同权限要求的InfoManager
     * 
     * 
@param auth
     * 
@return
     
*/
    
public static InfoManager getSelectivityAuthInstance(AuthProxy auth) {
        Enhancer enhancer 
= new Enhancer();
        enhancer.setSuperclass(InfoManager.
class);
        enhancer.setCallbacks(
new Callback[] { auth, NoOp.INSTANCE });
        enhancer.setCallbackFilter(
new AuthProxyFilter());
        
return (InfoManager) enhancer.create();
    }

}
记住:setCallbacks中的拦截器(interceptor)的顺序,一定要和CallbackFilter里面指定的顺序一致!!切忌。

Client.java
public class Client {

    
public static void main(String[] args) {
        Client c 
= new Client();
        c.selectivityAuthManager();
    }
    
    
/**
     * 模拟:没有权限的会员,可以作查询操作
     
*/
    
public void selectivityAuthManager() {
        System.out.println(
"the loginer's name is not maurice,so have no permits do manager except do query operator");
        InfoManager authManager 
= InfoManagerFactory.getSelectivityAuthInstance(new AuthProxy("maurice1"));
        doCRUD(authManager);
        separatorLine();
    }

    
/**
     * 对Info做增加/更新/删除/查询操作
     * 
     * 
@param manager
     
*/
    
private void doCRUD(InfoManager manager) {
        manager.create();
        manager.update();
        manager.delete();
        manager.query();
    }

    
/**
     * 加一个分隔行,用于区分
     
*/
    
private void separatorLine() {
        System.out.println(
"################################");
    }

}
此时,对于query的权限校验已经被去掉了。


通过一个模拟需求,简单介绍了cglib aop功能的使用。
CGlib应用非常广,在spring,hibernate等框架中,被大量的使用。


CGlib原理:
cglib神奇吗?其实一旦了解cglib enhancer的原理,一切就真相大白了。
刚才在第二部分中,有个疑问:enhancer.create()到底返回了什么对象?

其实在刚才的例子中,cglib在代码运行期,动态生成了InfoManager的子类,并且根据CallbackFilter的accept方法,覆写了InfoManager中的所有方法--去执行相应的MethodInterceptor的intercept方法。

有兴趣的朋友可以看看我反编译的InfoManager的子类,就可以很明白知道具体的实现了。(需要有耐心才可以)
InfoManager$$EnhancerByCGLIB$$de624598.jad
// Decompiled by Jad v1.5.8e. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.geocities.com/kpdus/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   <generated>

package cn.eulic.codelab.cglib;

import java.lang.reflect.Method;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.*;

// Referenced classes of package cn.eulic.codelab.cglib:
//            InfoManager

public class CGLIB.BIND_CALLBACKS extends InfoManager
    
implements Factory
{

    
static void CGLIB$STATICHOOK1()
    {
        Class class1;
        ClassLoader classloader;
        CGLIB$THREAD_CALLBACKS 
= new ThreadLocal();
        classloader 
= (class1 = Class.forName("cn.eulic.codelab.cglib.InfoManager$$EnhancerByCGLIB$$de624598")).getClassLoader();
        classloader;
        CGLIB$emptyArgs 
= new Object[0];
        CGLIB$delete$
0$Proxy = MethodProxy.create(classloader, (CGLIB$delete$0$Method = Class.forName("cn.eulic.codelab.cglib.InfoManager").getDeclaredMethod("delete"new Class[0])).getDeclaringClass(), class1, "()V""delete""CGLIB$delete$0");
        CGLIB$create$
1$Proxy = MethodProxy.create(classloader, (CGLIB$create$1$Method = Class.forName("cn.eulic.codelab.cglib.InfoManager").getDeclaredMethod("create"new Class[0])).getDeclaringClass(), class1, "()V""create""CGLIB$create$1");
        CGLIB$query$
2$Proxy = MethodProxy.create(classloader, (CGLIB$query$2$Method = Class.forName("cn.eulic.codelab.cglib.InfoManager").getDeclaredMethod("query"new Class[0])).getDeclaringClass(), class1, "()V""query""CGLIB$query$2");
        CGLIB$update$
3$Proxy = MethodProxy.create(classloader, (CGLIB$update$3$Method = Class.forName("cn.eulic.codelab.cglib.InfoManager").getDeclaredMethod("update"new Class[0])).getDeclaringClass(), class1, "()V""update""CGLIB$update$3");
        CGLIB$finalize$
4$Proxy = MethodProxy.create(classloader, (CGLIB$finalize$4$Method = Class.forName("java.lang.Object").getDeclaredMethod("finalize"new Class[0])).getDeclaringClass(), class1, "()V""finalize""CGLIB$finalize$4");
        CGLIB$hashCode$
5$Proxy = MethodProxy.create(classloader, (CGLIB$hashCode$5$Method = Class.forName("java.lang.Object").getDeclaredMethod("hashCode"new Class[0])).getDeclaringClass(), class1, "()I""hashCode""CGLIB$hashCode$5");
        CGLIB$clone$
6$Proxy = MethodProxy.create(classloader, (CGLIB$clone$6$Method = Class.forName("java.lang.Object").getDeclaredMethod("clone"new Class[0])).getDeclaringClass(), class1, "()Ljava/lang/Object;""clone""CGLIB$clone$6");
        CGLIB$equals$
7$Proxy = MethodProxy.create(classloader, (CGLIB$equals$7$Method = Class.forName("java.lang.Object").getDeclaredMethod("equals"new Class[] {
            Class.forName(
"java.lang.Object")
        })).getDeclaringClass(), class1, 
"(Ljava/lang/Object;)Z""equals""CGLIB$equals$7");
        CGLIB$toString$
8$Proxy = MethodProxy.create(classloader, (CGLIB$toString$8$Method = Class.forName("java.lang.Object").getDeclaredMethod("toString"new Class[0])).getDeclaringClass(), class1, "()Ljava/lang/String;""toString""CGLIB$toString$8");
        
return;
    }

    
final void CGLIB$delete$0()
    {
        
super.delete();
    }

    
public final void delete()
    {
        CGLIB$CALLBACK_0;
        
if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
_L1:
        JVM INSTR pop ;
        CGLIB$BIND_CALLBACKS(
this);
        CGLIB$CALLBACK_0;
_L2:
        JVM INSTR dup ;
        JVM INSTR ifnull 
37;
           
goto _L3 _L4
_L3:
        
break MISSING_BLOCK_LABEL_21;
_L4:
        
break MISSING_BLOCK_LABEL_37;
        
this;
        CGLIB$delete$
0$Method;
        CGLIB$emptyArgs;
        CGLIB$delete$
0$Proxy;
        intercept();
        
return;
        
super.delete();
        
return;
    }

    
final void CGLIB$create$1()
    {
        
super.create();
    }

    
public final void create()
    {
        CGLIB$CALLBACK_0;
        
if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
_L1:
        JVM INSTR pop ;
        CGLIB$BIND_CALLBACKS(
this);
        CGLIB$CALLBACK_0;
_L2:
        JVM INSTR dup ;
        JVM INSTR ifnull 
37;
           
goto _L3 _L4
_L3:
        
break MISSING_BLOCK_LABEL_21;
_L4:
        
break MISSING_BLOCK_LABEL_37;
        
this;
        CGLIB$create$
1$Method;
        CGLIB$emptyArgs;
        CGLIB$create$
1$Proxy;
        intercept();
        
return;
        
super.create();
        
return;
    }

    
final void CGLIB$query$2()
    {
        
super.query();
    }

    
public final void query()
    {
        CGLIB$CALLBACK_0;
        
if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
_L1:
        JVM INSTR pop ;
        CGLIB$BIND_CALLBACKS(
this);
        CGLIB$CALLBACK_0;
_L2:
        JVM INSTR dup ;
        JVM INSTR ifnull 
37;
           
goto _L3 _L4
_L3:
        
break MISSING_BLOCK_LABEL_21;
_L4:
        
break MISSING_BLOCK_LABEL_37;
        
this;
        CGLIB$query$
2$Method;
        CGLIB$emptyArgs;
        CGLIB$query$
2$Proxy;
        intercept();
        
return;
        
super.query();
        
return;
    }

    
final void CGLIB$update$3()
    {
        
super.update();
    }

    
public final void update()
    {
        CGLIB$CALLBACK_0;
        
if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
_L1:
        JVM INSTR pop ;
        CGLIB$BIND_CALLBACKS(
this);
        CGLIB$CALLBACK_0;
_L2:
        JVM INSTR dup ;
        JVM INSTR ifnull 
37;
           
goto _L3 _L4
_L3:
        
break MISSING_BLOCK_LABEL_21;
_L4:
        
break MISSING_BLOCK_LABEL_37;
        
this;
        CGLIB$update$
3$Method;
        CGLIB$emptyArgs;
        CGLIB$update$
3$Proxy;
        intercept();
        
return;
        
super.update();
        
return;
    }

    
final void CGLIB$finalize$4()
        
throws Throwable
    {
        
super.finalize();
    }

    
protected final void finalize()
        
throws Throwable
    {
        CGLIB$CALLBACK_0;
        
if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
_L1:
        JVM INSTR pop ;
        CGLIB$BIND_CALLBACKS(
this);
        CGLIB$CALLBACK_0;
_L2:
        JVM INSTR dup ;
        JVM INSTR ifnull 
37;
           
goto _L3 _L4
_L3:
        
break MISSING_BLOCK_LABEL_21;
_L4:
        
break MISSING_BLOCK_LABEL_37;
        
this;
        CGLIB$finalize$
4$Method;
        CGLIB$emptyArgs;
        CGLIB$finalize$
4$Proxy;
        intercept();
        
return;
        
super.finalize();
        
return;
    }

    
final int CGLIB$hashCode$5()
    {
        
return super.hashCode();
    }

    
public final int hashCode()
    {
        CGLIB$CALLBACK_0;
        
if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
_L1:
        JVM INSTR pop ;
        CGLIB$BIND_CALLBACKS(
this);
        CGLIB$CALLBACK_0;
_L2:
        JVM INSTR dup ;
        JVM INSTR ifnull 
52;
           
goto _L3 _L4
_L3:
        
this;
        CGLIB$hashCode$
5$Method;
        CGLIB$emptyArgs;
        CGLIB$hashCode$
5$Proxy;
        intercept();
        JVM INSTR dup ;
        JVM INSTR ifnonnull 
45;
           
goto _L5 _L6
_L5:
        JVM INSTR pop ;
        
0;
          
goto _L7
_L6:
        (Number);
        intValue();
_L7:
        
return;
_L4:
        
return super.hashCode();
    }

    
final Object CGLIB$clone$6()
        
throws CloneNotSupportedException
    {
        
return super.clone();
    }

    
protected final Object clone()
        
throws CloneNotSupportedException
    {
        CGLIB$CALLBACK_0;
        
if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
_L1:
        JVM INSTR pop ;
        CGLIB$BIND_CALLBACKS(
this);
        CGLIB$CALLBACK_0;
_L2:
        JVM INSTR dup ;
        JVM INSTR ifnull 
37;
           
goto _L3 _L4
_L3:
        
this;
        CGLIB$clone$
6$Method;
        CGLIB$emptyArgs;
        CGLIB$clone$
6$Proxy;
        intercept();
        
return;
_L4:
        
return super.clone();
    }

    
final boolean CGLIB$equals$7(Object obj)
    {
        
return super.equals(obj);
    }

    
public final boolean equals(Object obj)
    {
        CGLIB$CALLBACK_0;
        
if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
_L1:
        JVM INSTR pop ;
        CGLIB$BIND_CALLBACKS(
this);
        CGLIB$CALLBACK_0;
_L2:
        JVM INSTR dup ;
        JVM INSTR ifnull 
57;
           
goto _L3 _L4
_L3:
        
this;
        CGLIB$equals$
7$Method;
        
new Object[] {
            obj
        };
        CGLIB$equals$
7$Proxy;
        intercept();
        JVM INSTR dup ;
        JVM INSTR ifnonnull 
50;
           
goto _L5 _L6
_L5:
        JVM INSTR pop ;
        
false;
          
goto _L7
_L6:
        (Boolean);
        booleanValue();
_L7:
        
return;
_L4:
        
return super.equals(obj);
    }

    
final String CGLIB$toString$8()
    {
        
return super.toString();
    }

    
public final String toString()
    {
        CGLIB$CALLBACK_0;
        
if(CGLIB$CALLBACK_0 != nullgoto _L2; else goto _L1
_L1:
        JVM INSTR pop ;
        CGLIB$BIND_CALLBACKS(
this);
        CGLIB$CALLBACK_0;
_L2:
        JVM INSTR dup ;
        JVM INSTR ifnull 
40;
           
goto _L3 _L4
_L3:
        
this;
        CGLIB$toString$
8$Method;
        CGLIB$emptyArgs;
        CGLIB$toString$
8$Proxy;
        intercept();
        (String);
        
return;
_L4:
        
return super.toString();
    }

    
public static MethodProxy CGLIB$findMethodProxy(Signature signature)
    {
        String s 
= signature.toString();
        s;
        s.hashCode();
        JVM INSTR lookupswitch 
9default 200
    
//                   -1949253108: 92
    
//                   -1574182249: 104
    
//                   -1166709331: 116
    
//                   -508378822: 128
    
//                   -358764054: 140
    
//                   598313209: 152
    
//                   1826985398: 164
    
//                   1913648695: 176
    
//                   1984935277: 188;
           goto _L1 _L2 _L3 _L4 _L5 _L6 _L7 _L8 _L9 _L10
_L2:
        
"update()V";
        equals();
        JVM INSTR ifeq 
201;
           
goto _L11 _L12
_L12:
        
break MISSING_BLOCK_LABEL_201;
_L11:
        
return CGLIB$update$3$Proxy;
_L3:
        
"finalize()V";
        equals();
        JVM INSTR ifeq 
201;
           
goto _L13 _L14
_L14:
        
break MISSING_BLOCK_LABEL_201;
_L13:
        
return CGLIB$finalize$4$Proxy;
_L4:
        
"query()V";
        equals();
        JVM INSTR ifeq 
201;
           
goto _L15 _L16
_L16:
        
break MISSING_BLOCK_LABEL_201;
_L15:
        
return CGLIB$query$2$Proxy;
_L5:
        
"clone()Ljava/lang/Object;";
        equals();
        JVM INSTR ifeq 
201;
           
goto _L17 _L18
_L18:
        
break MISSING_BLOCK_LABEL_201;
_L17:
        
return CGLIB$clone$6$Proxy;
_L6:
        
"delete()V";
        equals();
        JVM INSTR ifeq 
201;
           
goto _L19 _L20
_L20:
        
break MISSING_BLOCK_LABEL_201;
_L19:
        
return CGLIB$delete$0$Proxy;
_L7:
        
"create()V";
        equals();
        JVM INSTR ifeq 
201;
           
goto _L21 _L22
_L22:
        
break MISSING_BLOCK_LABEL_201;
_L21:
        
return CGLIB$create$1$Proxy;
_L8:
        
"equals(Ljava/lang/Object;)Z";
        equals();
        JVM INSTR ifeq 
201;
           
goto _L23 _L24
_L24:
        
break MISSING_BLOCK_LABEL_201;
_L23:
        
return CGLIB$equals$7$Proxy;
_L9:
        
"toString()Ljava/lang/String;";
        equals();
        JVM INSTR ifeq 
201;
           
goto _L25 _L26
_L26:
        
break MISSING_BLOCK_LABEL_201;
_L25:
        
return CGLIB$toString$8$Proxy;
_L10:
        
"hashCode()I";
        equals();
        JVM INSTR ifeq 
201;
           
goto _L27 _L28
_L28:
        
break MISSING_BLOCK_LABEL_201;
_L27:
        
return CGLIB$hashCode$5$Proxy;
_L1:
        JVM INSTR pop ;
        
return null;
    }

    
public static void CGLIB$SET_THREAD_CALLBACKS(Callback acallback[])
    {
        CGLIB$THREAD_CALLBACKS.set(acallback);
    }

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

    
private static final void CGLIB$BIND_CALLBACKS(Object obj)
    {
        CGLIB.STATIC_CALLBACKS static_callbacks 
= (CGLIB.STATIC_CALLBACKS)obj;
        
if(static_callbacks.CGLIB$BOUND) goto _L2; else goto _L1
_L1:
        Object obj1;
        static_callbacks.CGLIB$BOUND 
= true;
        obj1 
= CGLIB$THREAD_CALLBACKS.get();
        obj1;
        
if(obj1 != nullgoto _L4; else goto _L3
_L3:
        JVM INSTR pop ;
        CGLIB$STATIC_CALLBACKS;
        
if(CGLIB$STATIC_CALLBACKS != nullgoto _L4; else goto _L5
_L5:
        JVM INSTR pop ;
          
goto _L2
_L4:
        (Callback[]);
        static_callbacks;
        JVM INSTR swap ;
        
0;
        JVM INSTR aaload ;
        (MethodInterceptor);
        CGLIB$CALLBACK_0;
_L2:
    }

    
public Object newInstance(Callback acallback[])
    {
        CGLIB$SET_THREAD_CALLBACKS(acallback);
        CGLIB$SET_THREAD_CALLBACKS(
null);
        
return new <init>();
    }

    
public Object newInstance(Callback callback)
    {
        CGLIB$SET_THREAD_CALLBACKS(
new Callback[] {
            callback
        });
        CGLIB$SET_THREAD_CALLBACKS(
null);
        
return new <init>();
    }

    
public Object newInstance(Class aclass[], Object aobj[], Callback acallback[])
    {
        CGLIB$SET_THREAD_CALLBACKS(acallback);
        JVM INSTR 
new #2   <Class InfoManager$$EnhancerByCGLIB$$de624598>;
        JVM INSTR dup ;
        aclass;
        aclass.length;
        JVM INSTR tableswitch 
0 0default 35
    
//                   0 28;
           goto _L1 _L2
_L2:
        JVM INSTR pop ;
        
<init>();
          
goto _L3
_L1:
        JVM INSTR pop ;
        
throw new IllegalArgumentException("Constructor not found");
_L3:
        CGLIB$SET_THREAD_CALLBACKS(
null);
        
return;
    }

    
public Callback getCallback(int i)
    {
        CGLIB$BIND_CALLBACKS(
this);
        
this;
        i;
        JVM INSTR tableswitch 
0 0default 30
    
//                   0 24;
           goto _L1 _L2
_L2:
        CGLIB$CALLBACK_0;
          
goto _L3
_L1:
        JVM INSTR pop ;
        
null;
_L3:
        
return;
    }

    
public void setCallback(int i, Callback callback)
    {
        
this;
        callback;
        i;
        JVM INSTR tableswitch 
0 0default 29
    
//                   0 20;
           goto _L1 _L2
_L2:
        (MethodInterceptor);
        CGLIB$CALLBACK_0;
          
goto _L3
_L1:
        JVM INSTR pop2 ;
_L3:
    }

    
public Callback[] getCallbacks()
    {
        CGLIB$BIND_CALLBACKS(
this);
        
this;
        
return (new Callback[] {
            CGLIB$CALLBACK_0
        });
    }

    
public void setCallbacks(Callback acallback[])
    {
        
this;
        acallback;
        JVM INSTR dup2 ;
        
0;
        JVM INSTR aaload ;
        (MethodInterceptor);
        CGLIB$CALLBACK_0;
    }

    
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$delete$0$Method;
    
private static final MethodProxy CGLIB$delete$0$Proxy;
    
private static final Object CGLIB$emptyArgs[];
    
private static final Method CGLIB$create$1$Method;
    
private static final MethodProxy CGLIB$create$1$Proxy;
    
private static final Method CGLIB$query$2$Method;
    
private static final MethodProxy CGLIB$query$2$Proxy;
    
private static final Method CGLIB$update$3$Method;
    
private static final MethodProxy CGLIB$update$3$Proxy;
    
private static final Method CGLIB$finalize$4$Method;
    
private static final MethodProxy CGLIB$finalize$4$Proxy;
    
private static final Method CGLIB$hashCode$5$Method;
    
private static final MethodProxy CGLIB$hashCode$5$Proxy;
    
private static final Method CGLIB$clone$6$Method;
    
private static final MethodProxy CGLIB$clone$6$Proxy;
    
private static final Method CGLIB$equals$7$Method;
    
private static final MethodProxy CGLIB$equals$7$Proxy;
    
private static final Method CGLIB$toString$8$Method;
    
private static final MethodProxy CGLIB$toString$8$Proxy;

    
static 
    {
        CGLIB$STATICHOOK1();
    }

    
public ()
    {
        CGLIB$BIND_CALLBACKS(
this);
    }
}


附件如下:
cglib sample

posted on 2008-03-16 22:50 stone2083 阅读(35586) 评论(22)  编辑  收藏 所属分类: java

Feedback

# re: CGlib简单介绍 2008-07-03 16:51 zhen

用cglib也产生了附加的问题  回复  更多评论   

# re: CGlib简单介绍 2008-07-03 22:07 stone2083

不可否认,每项技术总会存在弊端,比如cglib,导致jvm Permanet Generation 不再稳定,如果配置不当,并且大量生成cglib代理类的时候,出现out of memory;
又或者,调试代理类的时候,相当不方便...
但是cglib有他可喜的一面,底层采用asm,动态生成字节码,比jdk proxy效率高了不知多少;为spring aop提供了底层的一种实现;hibernate使用cglib动态生成DO/PO (接口层对象)字节码...应用是何等的广泛.
为java静态语言提供了动态特性(当然,底层是asm功劳),多么可喜.

我不清楚,你所谓使用cglib产生附加问题,具体是什么问题?  回复  更多评论   

# re: CGlib简单介绍 2008-10-03 21:34 大鹏

太强了,我顶!  回复  更多评论   

# re: CGlib简单介绍 2009-05-05 16:16 SunnyWolf

NB  回复  更多评论   

# re: CGlib简单介绍 2009-09-16 11:04 tomcatlee

牛掰的东东啊  回复  更多评论   

# re: CGlib简单介绍 2009-10-09 16:40 名扬/六耶子

可以通过cglib动态创建java对象么?就是传入对象名,字段名,然后创建并返回所创建对象的实例?  回复  更多评论   

# re: CGlib简单介绍 2009-10-10 10:38 stone2083

@名扬/六耶子
cglib底层依赖了asm,它主要是在“动态代理”场景下增加易用性。
如果要动态生成字段,方法,那么asm或者javassist这两个技术,更合适你。  回复  更多评论   

# re: CGlib简单介绍[未登录] 2010-04-08 16:49 tylerLimin

不错!  回复  更多评论   

# re: CGlib简单介绍[未登录] 2010-09-28 22:46 pyzhu

"有兴趣的朋友可以看看我反编译的InfoManager的子类,就可以很明白知道具体的实现了。"
这个cglib在运行期动态生成的class你是如何获取的,并用jad进行反编码的?
一直没找到这个动态生成的class我也就无法对它进行反编译,莫非是直接放在jvm的堆内存了吧?那该如何获取它并反编译它呢。。。
期待答复~  回复  更多评论   

# re: CGlib简单介绍 2010-09-29 09:18 stone2083

@pyzhu
用了比较猥琐的办法,
debug,将动态生成class的字节码 输入到文件中,然后反编译得到的.  回复  更多评论   

# re: CGlib简单介绍[未登录] 2010-09-29 23:11 pyzhu

@stone2083
一语惊醒梦中人,呵呵。。。
可是还有些不明白的地方,如何通过Class对象获取对应class字节码呀?  回复  更多评论   

# re: CGlib简单介绍[未登录] 2010-09-29 23:22 pyzhu

@stone2083
呵呵。。。想到一种方式,用javassist的ClassPool/CtClass应该可以做到~  回复  更多评论   

# re: CGlib简单介绍[未登录] 2010-10-06 01:36 pyzhu

我发现我真是傻呀,竟然一直去寻找这样一种方式:“如何通过Class实例对象得到class字节码,然后将字节码写入文件再反编译,如此来获取源码”。。。
哈哈。。。真是笨得要命哦~
反倒忘记了cglib的source code了,嘻嘻。。。直接修改net.sf.cglib.core.AbstractClassGenerator.create(Object key)方法,将cglib取到的字节码写入文档再反编译不就ok了么~

ps. javassist貌似不行  回复  更多评论   

# re: CGlib简单介绍 2010-10-09 09:27 stone2083

@pyzhu
修改源码也是一种方法 :)
我是在debug的时候,Variables窗体中,编写java代码,拿到class变量信息做自己的处理


  回复  更多评论   

# re: CGlib简单介绍 2010-11-03 13:31 stone2083

@pyzhu
得到同事指点,还有一种更好的方法:
system.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "指定输出目录"); 

详见:http://www.javaeye.com/topic/799827  回复  更多评论   

# re: CGlib简单介绍 2011-11-09 15:21 yaohonv

学习  回复  更多评论   

# re: CGlib简单介绍 2013-10-24 16:14 挤馒头

楼主的代码有无限递归啊。。。  回复  更多评论   

# re: CGlib简单介绍 2013-10-24 16:18 挤馒头

@挤馒头
看错了,没问题  回复  更多评论   

# re: CGlib简单介绍 2013-11-06 22:26 diegozhu

@stone2083

1. PG 不再稳定.
2. debug困难.  回复  更多评论   

# re: CGlib简单介绍 2014-01-24 10:28 frogSF

反编译那段太难懂了~~~~
  回复  更多评论   

# re: CGlib简单介绍 2014-08-02 11:50 wanglj

受教了,谢谢!将代码download下来后,跑了跑,比之前的理解清晰多了。  回复  更多评论   

# re: CGlib简单介绍[未登录] 2015-10-05 11:41 jones

怎么反编译子类?  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航: