什么是Cglib

Cglib是一个强大的,高性能,高质量的代码生成类库。它可以在运行期扩展JAVA类与实现JAVA接口。其底层实现是通过ASM字节码处理框架来转换字节码并生成新的类。大部分功能实际上是ASM所提供的,Cglib只是封装了ASM,简化了ASM操作,实现了运行期生成新的class。

Cglib的原理

运行时动态的生成一个被代理类的子类(通过ASM字节码处理框架实现),子类重写了被代理类中所有非final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势植入横切逻辑。

Cglib优缺点

优点:JDK动态代理要求被代理的类必须实现接口,当需要代理的类没有实现接口时Cglib代理是一个很好的选择。另一个优点是Cglib动态代理比使用java反射的JDK动态代理要快(Cglib的FastClass机制,解析参考http://www.cnblogs.com/cruze/p/3865180.html#lable3

缺点:对于被代理类中的final方法,无法进行代理,因为子类中无法重写final函数

Cglib类库

net.sf.cglib.core:底层字节码处理类,他们大部分与ASM有关系。

net.sf.cglib.transform:编译期或运行期类和类文件的转换

net.sf.cglib.proxy:实现创建代理和方法拦截器的类

net.sf.cglib.reflect:实现快速反射和C#风格代理的类

net.sf.cglib.util:集合排序等工具类

net.sf.cglib.beans:JavaBean相关的工具类

最主要的一个接口CallBack接口,即回调接口,下面的拦截器、过滤器、延迟加载都继承于它,结构图如下:

动态代理之Cglib浅析

 

Cglib的拦截器和过滤器

拦截器:实现MethodInterceptor接口的类,在intercept方法中实现对代理目标类的方法拦截。但同时Cglib为简化和提高性能提供了一些专门的回调类型如FixedValue(可以在实现的方法loadObject中指定返回固定值,而不调用目标类函数)、NoOp(把对回调方法的调用直接委派到这个方法的父类,即不进行拦截)

过滤器:实现CallbackFilter接口的类,通过accept方法返回一个下标值,用于指定调用哪个拦截器进行拦截处理

/**
 * @author longe
 *    被代理类
 */
public class TDao {
    public void create() {
        System.out.println("create() is running !");
    }

    public void query() {
        System.out.println("query() is running !");
    }

    public void update() {
        System.out.println("update() is running !");
    }

    public void delete() {
        System.out.println("delete() is running !");
    }
}

/**
 * @author longe
 *    过滤器
 */
public class TDaoCglibFilter implements CallbackFilter {

    public final static int NO_RESTRICTION = 0;
    public final static int RESTRICTION_CREATE = 1;
    
    
    /* (non-Javadoc)
     *    根据调用的方法返回使用的callbacks下标
     */
    @Override
    public int accept(Method method) {
        if(method.getName().startsWith("create")){
            return RESTRICTION_CREATE;
        }
        return NO_RESTRICTION;
    }
}

/**
 * @author longe
 * 拦截器
 */
public class TDaoCglibProxy implements MethodInterceptor {

    private String name;
    private Object objT;
    
    public TDaoCglibProxy(String name) {
        this.name = name;
    }
    public TDaoCglibProxy(Object obj,String name) {
        this.name = name;
        this.objT = obj;
    }
    
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        if(!name.equals("张三")){
            System.out.println("没有权限!");
            return null;
        }
//        return method.invoke(objT, args);    //通过反射进行调用
        return proxy.invokeSuper(obj, args);    //使用Cglib代理调用
    }


    public static void main(String[] args) {
        Enhancer en = new Enhancer();
        en.setSuperclass(TDao.class);
        TDaoCglibProxy callBack = new TDaoCglibProxy("张三1");
//        指定两个callback,通过callBackFilter返回的下标值控制调用使用那一个callback处理
        en.setCallbacks(new Callback[] { NoOp.INSTANCE, callBack });
//        方法过滤器,根据过滤器返回不同的值回调对应下标的Callback方法
        en.setCallbackFilter(new TDaoCglibFilter());
        TDao dao = (TDao) en.create();
        dao.create();
        dao.query();
        dao.update();
        dao.delete();
    }
    
}
代码示例

相关文章: