Java CGLib动态代理

不仅可以接管接口类的方法还可以接管普通类的方法

一些开源框架都采用了cglib:Hibernate Spring Guice 

CGLib 的底层是 Java 字节码操作框架——ASM (https://asm.ow2.io)

在JDK8之前CGLib动态代理比JDK的动态代理(使用Java反射)效率要高

唯一要注意的是,如果被代理的类被final修饰,那么它不可被继承,即不可被代理,同样如果被代理的类中存在final修饰的方法,那么该方法也不可被代理,因为CGLib原理是动态生成被代理类的子类

final类不能被继承,final方法不能被复写

导入maven依赖

        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
        </dependency>

目标接口

public interface TargetInterface {

    String sayHello(String name);

    String sayThanks(String name);

}

目标接口实现类

public class TargetInterfaceImpl implements TargetInterface{
    @Override
    public String sayHello(String name) {
        //限流
        return "Hello, " + name;
    }

    @Override
    public String sayThanks(String name) {
        //限流

        return "Thanks, " + name;
    }
}

cglib代理类



/**
 * author:qxstart
 * TargetProxy 类还不是一个真正的代理类,它是代理类的一部分
 */
public class TargetProxy implements MethodInterceptor {

    /**
     * 获取真正的代理类
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public <T> T getProxy(Class<T> clazz) {

        // 字节码增强的一个类
        Enhancer enhancer = new Enhancer();

        // 设置父类
        // enhancer.setSuperclass(clazz);
        enhancer.setInterfaces(new Class[]{clazz});

        // 设置回调类
        enhancer.setCallback(this);

        // 创建代理类
        return (T) enhancer.create();


    }


    /**
     * 既可以sayHello,也可以拦截 sayThanks
     *
     * @param obj
     * @param method
     * @param args
     * @param proxy
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // 方法之前执行逻辑
        System.out.println(method.getName() + "数据缓存start。。。。。。。");

        // 调用目标方法
        Object result = proxy.invokeSuper(obj, args);
        System.out.println(result);
        //如果设置父类为接口,就需要像mybatis一样自己实现接口
        // System.out.println("sayHello..........");

        // 方法之后执行逻辑
        System.out.println(method.getName() + "数据缓存end。。。。。。。");


        return result;
    }
}

测试类

public class Test {

    public static void main(String[] args) {

        // 通过参数设置,把动态代理生成的class文件输出到磁盘上,默认是不会输出到磁盘的,所以动态代理生成的类我们是看不见摸不着的
        // System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"D:/code");

        TargetProxy targetProxy = new TargetProxy();

        // 拿到目标类的代理类
        //如果目标代理类TargetProxy中通过 enhancer.setSuperclass(clazz) 设置父类, 那么这里的targetProxy.getProxy(TargetInterfaceImpl.class); 传入目标接口的实现类
        TargetInterface targetInterface = targetProxy.getProxy(TargetInterfaceImpl.class);

        //如果目标代理类TargetProxy中通过 enhancer.setInterfaces(new Class[]{clazz}) 设置父类, 那么这里 targetProxy.getProxy(TargetInterface.class); 传入用目标接口  并且TargetProxy的invoke方法中的 调用目标方法这一句 (Object result = proxy.invokeSuper(obj, args)) 需要重写目标接口的方法

        // TargetInterface targetInterface = targetProxy.getProxy(TargetInterface.class);

        targetInterface.sayHello("张无忌");
        targetInterface.sayThanks("张无忌");


    }


}

输出结果

Java JDK动态代理_Excellent999的博客-CSDN博客

Java Javassist动态代理-CSDN博客

Java 静态代理-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值