CGlib动态代理

一、CGlib介绍

参考链接:设计模式之代理模式https://www.cnblogs.com/lixiuyu/p/5919643.html

CGlib(Code Generation Library)是一个强大的,高性能的代码生成库。

它被广泛使用在基于代理的AOP框架(例如Spring AOP和dynaop)提供方法拦截(interception)。

它可以在运行期扩展Java类与实现Java接口。(jdk中的proxy必须基于接口,cglib却没有这个限制。)

CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。

二、CGlib动态代理实例 

1、定义一个服务类,不实现任何接口,有两个方法,其中一个方法用final修饰。

(如果委托类被最终修饰,那么它不可被继承,即不可被代理;

 同样,如果委托类中存在final修饰的方法,那么该方法也不可被代理;)

public class HelloService {
 
    public HelloService() {
        System.out.println("HelloService构造");
    }
 
    /**
     * 该方法不能被子类覆盖,Cglib是无法代理final修饰的方法的
     */
    final public String sayOthers(String name) {
        System.out.println("HelloService:sayOthers>>"+name);
        return null;
    }
 
    public void sayHello() {
        System.out.println("HelloService:sayHello");
    }
}

2、定义一个自定义MethodInterceptor (可以在intercept方法中实现权限拦截等)

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

 3、生成CGLIB代理对象调用目标方法

public class Client {
    public static void main(String[] args) {
        // 代理类class文件存入本地磁盘方便我们反编译查看源码
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\code");
        // 通过CGLIB动态代理获取代理对象的过程
        Enhancer enhancer = new Enhancer();
        // 设置enhancer对象的父类
        enhancer.setSuperclass(HelloService.class);
        // 设置enhancer的回调对象
        enhancer.setCallback(new MyMethodInterceptor());
        // 创建代理对象
        HelloService proxy= (HelloService)enhancer.create();
        // 通过代理对象调用目标方法
        proxy.sayHello();
    }
}

4、运行结果

 HelloService构造

======插入前置通知======

HelloService:sayHello

======插入后者通知======

三、分析

调用过程:

代理对象调用this.sayHello方法->调用拦截器->methodProxy.invokeSuper->CGLIB$sayHello$0->被代理对象的sayHello方法。

拦截器MethodInterceptor中就是由MethodProxy的invokeSuper方法调用代理方法的。

Cglib动态代理执行代理方法效率之所以比JDK的高是因为Cglib采用了FastClass机制,它的原理简单来说就是:为代理类和被代理类各生成一个Class,这个Class会为代理类或被代理类的方法分配一个index(int类型)。 这个index当做一个入参,FastClass就可以直接定位要调用的方法直接进行调用,这样省去了反射调用。

 

参考链接:

(源码分析)

https://blog.csdn.net/yhl_jxy/article/details/80633194

https://www.cnblogs.com/monkey0307/p/8328821.html

(实例,CallbackFilter)

https://blog.csdn.net/gotohbu/article/details/4357293

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值