展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > Java中如何实现动态代理?CGLib与JDK Proxy对比

Java中如何实现动态代理?CGLib与JDK Proxy对比

JDKProxy基于接口,通过反射生成代理类,适用于有接口的目标对象;CGLib通过字节码生成子类,适用于无接口的类。1.JDKProxy要求目标类实现接口,通过InvocationHandler拦截方法调用,适合接口编程场景。2.CGLib不依赖接口,使用MethodInterceptor拦截方法,通过继承目标类生成代理,适合无接口的类。3.选择时优先考虑JDKProxy,若目标类无接口则使用CGLib。两者性能差异在现代JVM中通常可忽略,实际应用中应根据是否具备接口及依赖管理进行决策。

本文目录

    JDK Proxy基于接口,通过反射生成代理类,适用于有接口的目标对象;CGLib通过字节码生成子类,适用于无接口的类。1. JDK Proxy要求目标类实现接口,通过InvocationHandler拦截方法调用,适合接口编程场景。2. CGLib不依赖接口,使用MethodInterceptor拦截方法,通过继承目标类生成代理,适合无接口的类。3. 选择时优先考虑JDK Proxy,若目标类无接口则使用CGLib。两者性能差异在现代JVM中通常可忽略,实际应用中应根据是否具备接口及依赖管理进行决策。

    Java中如何实现动态代理?CGLib与JDK Proxy对比

    Java中实现动态代理,核心在于运行时创建代理对象,拦截并增强目标对象的方法调用。JDK Proxy基于接口,通过反射机制在运行时生成代理类;而CGLib则不依赖接口,它通过修改字节码、生成目标类的子类来实现代理。选择哪种方式,往往取决于你的目标对象是否有接口,以及对性能、依赖的考量。

    Java中如何实现动态代理?CGLib与JDK Proxy对比

    解决方案

    1. JDK Proxy实现动态代理

    Java中如何实现动态代理?CGLib与JDK Proxy对比

    JDK Proxy是Java标准库自带的动态代理机制,它要求被代理的类必须实现一个或多个接口。

    // 1. 定义业务接口
    public interface Subject {
        void request();
        String sayHello(String name);
    }
    
    // 2. 实现业务接口的真实对象
    public class RealSubject implements Subject {
        @Override
        public void request() {
            System.out.println("RealSubject: Executing request...");
        }
    
        @Override
        public String sayHello(String name) {
            return "RealSubject: Hello, " + name + "!";
        }
    }
    
    // 3. 定义一个InvocationHandler,用于处理代理实例上的方法调用
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class MyInvocationHandler implements InvocationHandler {
        private Object target; // 真实对象
    
        public MyInvocationHandler(Object target) {
            this.target = target;
        }
    
        /**
         * proxy: 代理实例
         * method: 调用的方法
         * args: 方法参数
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("MyInvocationHandler: Before method " + method.getName());
            // 调用真实对象的方法
            Object result = method.invoke(target, args);
            System.out.println("MyInvocationHandler: After method " + method.getName());
            return result;
        }
    
        // 获取代理对象
        public Object getProxy() {
            return Proxy.newProxyInstance(
                    target.getClass().getClassLoader(), // 类加载器
                    target.getClass().getInterfaces(),   // 真实对象实现的接口
                    this                                 // InvocationHandler实例
            );
        }
    }
    
    // 4. 使用示例
    public class JdkProxyDemo {
        public static void main(String[] args) {
            RealSubject realSubject = new RealSubject();
            MyInvocationHandler handler = new MyInvocationHandler(realSubject);
            Subject proxySubject = (Subject) handler.getProxy(); // 获取代理对象
    
            proxySubject.request();
            System.out.println(proxySubject.sayHello("World"));
    
            // 验证代理对象类型
            System.out.println("Proxy class: " + proxySubject.getClass().getName());
            System.out.println("Is proxy an instance of Subject? " + (proxySubject instanceof Subject));
        }
    }

    2. CGLib实现动态代理

    Java中如何实现动态代理?CGLib与JDK Proxy对比

    CGLib (Code Generation Library) 是一个强大的高性能字节码生成库,它可以在运行时扩展Java类和实现Java接口。它不需要被代理类实现接口,通过生成目标类的子类来实现代理。

    // 1. 定义一个普通类,无需实现接口
    public class TargetClass {
        public void doSomething() {
            System.out.println("TargetClass: Doing something...");
        }
    
        public String greet(String name) {
            return "TargetClass: Hello, " + name + "!";
        }
    }
    
    // 2. 定义一个MethodInterceptor,用于拦截方法调用
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    import java.lang.reflect.Method;
    
    public class MyMethodInterceptor implements MethodInterceptor {
        /**
         * obj: CGLib生成的代理对象
         * method: 调用的方法
         * args: 方法参数
         * methodProxy: 用于调用父类方法(即目标类方法)的代理
         */
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println("MyMethodInterceptor: Before method " + method.getName());
            // 调用目标对象的方法,这里通过methodProxy调用,性能更高
            Object result = methodProxy.invokeSuper(obj, args);
            System.out.println("MyMethodInterceptor: After method " + method.getName());
            return result;
        }
    
        // 获取代理对象
        public Object getProxy(Class targetClass) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(targetClass); // 设置目标类作为父类
            enhancer.setCallback(this);          // 设置回调
            return enhancer.create();            // 创建代理对象
        }
    }
    
    // 3. 使用示例
    public class CglibProxyDemo {
        public static void main(String[] args) {
            MyMethodInterceptor interceptor = new MyMethodInterceptor();
            TargetClass proxyTarget = (TargetClass) interceptor.getProxy(TargetClass.class);
    
            proxyTarget.doSomething();
            System.out.println(proxyTarget.greet("CGLib User"));
    
            // 验证代理对象类型
            System.out.println("Proxy class: " + proxyTarget.getClass().getName());
            System.out.println("Is proxy an instance of TargetClass? " + (proxyTarget instanceof TargetClass));
        }
    }

    JDK Proxy的工作原理与适用场景是什么?

    JDK Proxy的工作原理,说白了就是Java在运行时,动态地为你生成一个实现了目标接口的“假”类。这个“假”类,也就是代理类,它会把所有对接口方法的调用,都转发给一个你提供的InvocationHandler实例去处理。InvocationHandler的invoke方法接收到这些调用后,就能在调用真实方法前后加入你的逻辑,比如日志记录、事务管理、权限校验等等。它底层依赖的是Java的反射机制,通过Proxy.newProxyInstance()方法,JVM会为你创建一个临时的、实现了指定接口的代理类字节码,并加载到内存中。

    这种机制最典型的适用场景,就是那些基于接口编程的框架。比如Spring AOP,当你配置一个接口的Service进行事务管理时,Spring默认就会使用JDK Proxy。还有RPC框架,客户端 stub 通常就是通过JDK Proxy生成的,它把远程调用封装成一个本地接口方法。再比如一些单元测试的Mock框架,也能用它来模拟接口行为。简而言之,只要你的设计中大量使用了接口,并且希望在不修改原有代码的前提下,为接口方法添加统一的横切逻辑,JDK Proxy都是一个非常自然且强大的选择。它简洁、内置,用起来也相当顺手。

    CGLib动态代理的核心机制与优势在哪里?

    CGLib的核心机制与JDK Proxy大相径庭。它不依赖接口,而是通过字节码技术,直接生成目标类的子类。当你请求CGLib为一个类创建代理时,它会利用ASM库(一个字节码操作和分析框架)在运行时生成一个新的类,这个新类继承自你的目标类,并且会覆盖目标类中的所有非final方法。在这些被覆盖的方法中,CGLib会插入调用你提供的MethodInterceptor的逻辑。MethodInterceptor的intercept方法中,你就可以实现自己的增强逻辑,并通过MethodProxy来调用父类(即原始目标类)的方法。

    CGLib的优势显而易见:它能代理那些没有实现接口的普通类。这在很多场景下非常有用,比如一些遗留系统,或者你就是不想为每个类都定义一个接口。另一个常常被提及的优势是性能。由于CGLib生成的是目标类的子类,直接调用子类方法,理论上比JDK Proxy通过反射调用invoke方法要快一些。不过,在现代JVM的优化下,这种性能差异在绝大多数应用中几乎可以忽略不计,除非你的应用对代理的调用是极其频繁且性能敏感的核心瓶颈。对我个人而言,CGLib更多的是解决“能否代理”的问题,而非“性能高低”的问题。

    JDK Proxy与CGLib在实际应用中该如何选择?

    在实际开发中,选择JDK Proxy还是CGLib,我通常会从几个维度去考量,而不是盲目地偏向某一方。

    我个人在做选择时,通常会先看有没有接口。如果被代理的类已经实现了接口,并且我只需要代理接口定义的方法,那么JDK Proxy往往是我的首选。它内置于JDK,无需额外依赖,代码也相对简洁直观。这就像是,如果有一条现成的、平坦的公路能到目的地,我肯定不会去开辟一条新的山路。

    另一边厢,如果目标类没有实现任何接口,或者我需要代理的是一个具体的类,而不仅仅是它的接口方法(比如,一个类中的某些方法并没有在任何接口中定义),那么CGLib就成了唯一的选择。很多框架,比如Spring AOP,在发现目标对象没有实现接口时,会自动切换到CGLib来创建代理。这种智能切换省去了开发者手动判断的麻烦。

    再者说,性能差异在大多数业务场景下并不构成决定性因素。现代JVM的JIT编译器对反射调用的优化已经相当出色,两者之间的性能差距远没有想象中那么大。如果你真的遇到了性能瓶颈,通常需要从更宏观的架构设计或算法层面去优化,而不是纠结于代理方式的微小性能差异。

    最后,考虑到外部依赖。JDK Proxy是JDK自带的,而CGLib需要引入第三方库。虽然这通常不是什么大问题,但在某些对依赖管理极其严格的环境中,内置方案可能会更受欢迎。

    所以,我的经验是:优先考虑JDK Proxy,因为它更“原生”;当且仅当JDK Proxy无法满足需求(即需要代理没有接口的类)时,才转向使用CGLib。 这种选择策略既能利用JDK的内置能力,又能应对更复杂的代理场景。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发
    相关文章 更多
    精品专题 更多
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    IOS软件

    正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

    AI

    正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

    Mac软件 更多
    Aperty macOS版
    Aperty macOS版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw macOS版
    AionClaw macOS版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy macOS版
    Loomy macOS版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirBuddy 3 macOS版
    AirBuddy 3 macOS版

    AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

    AirServer macOS版
    AirServer macOS版

    AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

    AnyDesk macOS版
    AnyDesk macOS版

    AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

    WINDOWS 更多
    讯飞绘文 网页版
    讯飞绘文 网页版

    讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

    Maya(Autodesk Maya) Windows版
    Maya(Autodesk Maya) Windows版

    Autodesk Maya 是面向影视、电视、动画和游戏行业的专业三维制作软件,集多边形与 NURBS 建模、角色绑定、关键帧和动作捕捉动画、Bifrost 特效模拟、材质开发及 Arnold 渲染于一体,

    Aperty Windows版
    Aperty Windows版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw Windows版
    AionClaw Windows版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy Windows版
    Loomy Windows版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirServer Windows版
    AirServer Windows版

    AirServer Windows版可把电脑变成AirPlay、Google Cast和Miracast无线投屏接收端,适合会议演示、课堂教学及家庭大屏分享。发送设备通常无需另装客户端,并可同时接收和智能排列多个镜像会话。