cglib动态代理实现及其原理浅析

Posted 八阿哥克星

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cglib动态代理实现及其原理浅析相关的知识,希望对你有一定的参考价值。

JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

举例:

1、定义被代理类:

public class CglibOrigin 
​
    public  CglibOrigin()
        System.out.println("CglibOrigin对象创建");
    
    public final void  finalMethod()
        System.out.println("final方法执行");
    
​
    public void  regularMethod()
        System.out.println("regularMethod方法执行");
    

2、定义拦截器,用以拦截被代理对象的方法(需要实现MenthodInterceptor接口)

public class MyMethodInterceptor implements MethodInterceptor 
​
    //Object o——生成的代理对象
    //Method——被代理对象的方法
    //Object[] objects——方法的参数
    //methodProxy——代理方法
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable 
        System.out.println("======插入前置通知======");
        ((CglibOrigin)o).regularMethod();
        Object object = methodProxy.invokeSuper(o, objects);
        System.out.println("======插入后者通知======");
        return object;
    

其中intercept()就是代理对象调用到方法时执行到的代码,即实现增强的代码部分;

而methodProxy.invokeSuper(o, objects)是执行被代理对象的方法;

3、测试

public class MyTest 
​
    @Test
    public void test()
        Enhancer enhancer = new Enhancer();
        //设置被代理类class
        enhancer.setSuperclass(CglibOrigin.class);
        //设置回调对象即拦截器
        enhancer.setCallback(new MyMethodInterceptor());
        //生成代理对象
        CglibOrigin origin = (CglibOrigin)enhancer.create();
        //调用方法
        origin.regularMethod();
    

这里的origin.regularMethod()方法,其实就是执行MyMethodInterceptor的intercept()。

生成的代理对象内部是这样的:

public final void sayHello() 

//enhancer中赋值给callback的拦截器对象

MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; ​ if (var10000 == null)  ​ CGLIB$BIND_CALLBACKS(this); ​ var10000 = this.CGLIB$CALLBACK_0; ​ 

    if (var10000 != null) 
    //调用拦截器MethodInterceptor的interceptor方法,完成增强
        var10000.intercept(this, CGLIB$sayHello$0$Method, CGLIB$emptyArgs, CGLIB$sayHello$0$Proxy);
     else 
        super.sayHello();
    

需要特别注意的是,CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。

 

(普通方法可以增强)

 

(final修饰的方法不可以增强)

jdk和cglib动态代理原理上的区别:

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

以上是关于cglib动态代理实现及其原理浅析的主要内容,如果未能解决你的问题,请参考以下文章

cglib动态代理实现及其原理浅析

设计模式----代理模式

jdk动态代理和cglib动态代理底层实现原理详细解析(cglib动态代理篇)

CGLib动态代理原理及实现

CGLib动态代理原理及实现

CGLib动态代理原理及实现