Cglib源码解析

      Cglib(Code Generator Library)是一个 java字节码生成工具,提供了一系列的类生成器,可以在运行期间,生成现有java类的子类(cglib不能扩展final类)。本系列文章分析cglib的源码实现。

一、基本框架


ClassGenerator是Cglib的核心接口,其中核心方法generateClass方法用于产生目标类;

public interface ClassGenerator {
    void generateClass(ClassVisitor var1) throws Exception;
}

AbstractClassGenerator抽象类实现了ClassGenerator接口,此类中并没有实现generateClass()方法,而是使用了模板方法设计模式,protected Object create()即为模板方法,其中byte[] b=this.strategy.generate(this)会调用继承类中实现的generateClass()方法。另外,AbstractClassGenerator中定义了一个静态内部类Source,其中name字段存储ClassGenerator的实现类全名,如net.sf.cglib.proxy.Enhancer;cache缓存用于存储该ClassGenerator生成的目标类,类型仍然是一个HashMap,类型为<ClassLoader,<Object,class>>。key为加载目标类的类加载器(针对同一个目标类,使用不同的类加载器加载,得到的class文件也不相同,因为需要以ClassLoader进行区分。),value仍然是一个hashmap,其中键值一般是Cglib中定义的类Key,value为目标类。为什么需要Key类呢?对于那些只与单个类相关的生成类,可以采用类名作为key。在动态代理中生成类不仅与目标类相关,还与使用的拦截类(MethodInterceptor),过滤类(CallbackFilter)相关,这样的话就要使用multi-vaules key来标识这个生成类。

protected static class Source {
    String name;
    Map cache = new WeakHashMap();

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

每个ClassGenerator具体实现类都有相应的缓存,如Enhancer类的静态块中定义source=new Source(Enhancer.class.getName())

二、目标类class文件的生成过程

我们以cglib动态代理为例来展示cglib生成class类文件的过程。我们有一个简单类UserServiceImp,用cglib动态生成其子类。

public class UserServiceImp {
    public String getName(int id){
        System.out.println("getName()");
        return "Tom";
    }
    public int getAge(int id){
        System.out.println("getAge()");
        return 10;
    }
}
首先需要定义一个实现拦截器实现MethodInterceptor接口,当生成的目标类调用UserServiceImp中的任何方法时都会被此类拦截,执行其中的intercept方法,此时会传入四个参数,o表示生成的目标类,method表示要调用的方法名,objects表示调用方法的参数,methodProxy要执行的方法的代理,UserServiceImp中的每个方法都会存在一个methodProxy方法代理。methodProxy.invokeSuper(o,objects)即调用真正的方法。

public class UserServiceMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
 
 
        Object obj=methodProxy.invokeSuper(o,objects);
        return obj;
    }
}

然后利用Enhancer生成器来生成目标类,如下所示

public class CglibDemo {
    public static void main(String[] args){
        UserServiceMethodInterceptor userServiceMethodInterceptor=new UserServiceMethodInterceptor();
        //实例化Enhancer类生成器
        Enhancer enhancer=new Enhancer();
        //设置Enhancer要生成的目标类的父类
        enhancer.setSuperclass(UserServiceImp.class);
        //设置目标类执行方法的拦截器
        enhancer.setCallback(userServiceMethodInterceptor);
        //利用enhancer生成目标类 UserServiceImp$$EnhancerByCGLIB$$b2b12b83@6df97b55
        UserServiceImp obj=(UserServiceImp) enhancer.create();
        //生成的目标类调用方法,此时会被userServiceMethodInterceptor拦截,执行其中的intercept方法
        obj.getName(1);
        //生成的目标类调用方法,此时会被userServiceMethodInterceptor拦截,执行其中的intercept方法
        obj.getAge(1);
    }
}

其中的关键方法时enhancer.create(),源码实现如下

public Object create() {
    this.classOnly = false;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值