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文件加载进来,通过修改其字节码生成子类来处理。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值