Java提高班(六)反射和动态代理(JDK Proxy和Cglib)
发布日期:2025-03-29 02:42:48 浏览次数:8 分类:精选文章

本文共 4040 字,大约阅读时间需要 13 分钟。

反射和动态代理虽然存在一定的关联,但将动态代理简单归结为反射机制的实现是不够全面的。实际上,动态代理是一种功能行为,其实现方式种类繁多。要理解这个问题,我们可以从反射与动态代理各自的特点和应用场景入手。

一、反射

反射是Java语言中提供的一项强大的功能,赋予程序在运行时自省的能力。通过反射,我们可以对类、对象进行操作,如获取类定义、获取属性和方法、调用方法、构造对象等。此外,反射甚至可以在运行时修改类定义。

1、获取类

反射中的类操作主要通过Class对象来实现。可以通过以下几种方式获得Class对象:

  • 通过forName()方法:使用Class.forName(name)工厂方法。例如:
    Class
    myClass = Class.forName("com.example.MyClass");
  • 通过getClass()方法:通过对对象调用getClass()方法。例如:
    MyClass obj = new MyClass();Class
    myClass = obj.getClass();
  • 直接获取类:通过对类直接调用class属性。例如:
    Class
    myClass = MyClass.class;
  • 2、类的常用方法

    反射中的Class对象提供了多种方法来获取类信息和执行操作:

    • 获取类名:使用getName()方法。如:

      String className = myClass.getName();
    • 获取父类:使用getSuperclass()方法。如:

      Class
      superClass = myClass.getSuperclass();
    • 获取实例对象:使用newInstance()方法。如:

      Object obj = myClass.newInstance();
    • 获取属性:使用getFields()getDeclaredFields()方法。如:

      Field[] allFields = myClass.getFields();
      Field[] declaredFields = myClass.getDeclaredFields();
    • 获取方法:使用getMethod()getDeclaredMethods()方法。如:

      Method[] allMethods = myClass.getMethods();
      Method[] declaredMethods = myClass.getDeclaredMethods();
    • 调用静态方法:使用invoke()方法。如:

      Method staticMethod = myClass.getMethod("staticMethod");staticMethod.invoke(myClass);
    • 调用非静态方法:需要有实例并设置访问权限。如下:

      Object instance = myClass.newInstance();Method nonStaticMethod = myClass.getMethod("nonStaticMethod");nonStaticMethod.invoke(instance);
    • 调用私有方法:需要设置可访问权限。如:

      Method privateMethod = myClass.getDeclaredMethod("privateMethod");privateMethod.setAccessible(true);privateMethod.invoke(instance);

    3、总结

    反射操作的核心包括:

  • 使用newInstance()获取类实例。
  • 使用getMethod(…)或`getDeclaredMethod(…)获取方法。
  • 使用`invoke(…)进行方法调用。
  • 通过setAccessible(true)设置访问权限。
  • 需要注意的是:在反射中,使用get*方法获取属性和方法时,携带“Declared”限定词的方法可以获取本类所有属性/方法(包括private属性/方法),而不携带则只能获取public属性/方法。

    二、动态代理

    动态代理是一种运行时动态构建代理和处理代理方法调用的机制,常用于RPC调用、AOP编程等场景。

    动态代理的实现方式多种多样,主要可分为两类:

    1、JDK Proxy 动态代理

    JDK Proxy动态代理基于反射机制,通过实现InvocationHandler接口来实现动态代理。代码示例如下:

    interface Animal {    void eat();}class Dog implements Animal {    @Override    public void eat() {        System.out.println("The dog is eating");    }}class Cat implements Animal {    @Override    public void eat() {        System.out.println("The cat is eating");    }}class AnimalProxy implements InvocationHandler {    private Object target;    public Object getInstance(Object target) {        this.target = target;        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("调用前");        Object result = method.invoke(target, args);        System.out.println("调用后");        return result;    }}public static void main(String[] args) {    AnimalProxy proxy = new AnimalProxy();    Animal dogProxy = (Animal) proxy.getInstance(new Dog());    dogProxy.eat();}

    2、Cglib 动态代理

    Cglib动态代理基于ASM框架,通过对目标类进行عية类生成,覆盖特定方法实现动态代理。适用于需要对 तरफ省方法实现扩展的场景。

    class Panda {    public void eat() {        System.out.println("The panda is eating");    }}class CglibProxy implements MethodInterceptor {    private Object target;    public Object getInstance(Object target) {        this.target = target;        Enhancer enhancer = new Enhancer();        enhancer.setSuperclass(target.getClass());        enhancer.setCallback(this);        return enhancer.create();    }    @Override    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {        System.out.println("调用前");        Object result = methodProxy.invokeSuper(o, objects);        System.out.println("调用后");        return result;    }}public static void main(String[] args) {    CglibProxy proxy = new CglibProxy();    Panda panda = (Panda) proxy.getInstance(new Panda());    panda.eat();}

    三、JDK Proxy 与 Cglib Compared

    JDK Proxy和Cglib的主要区别在于:

    1 J DK Proxy的优势:

    • 工作于标准类加载器下。
    • 可靠性高。
    • 维护成本低。
    • 易于实现,依赖少。

    2 Cglib 的优势:

    • 支持普通类代理。
    • 性能更高。
    • 方法拦截更灵活。

    3 综合考虑

    在实际应用中,需要根据项目需要选择适合的动态代理实现方式。JDK Proxy适合用于需要标准化接口的场景,而Cglib则适合对具体类进行动态代理更复杂的场景。

    本文所有示例代码均基于Java语言规范编写,避免使用任何外部资源或非标准编码。如需进一步了解Java反射与动态代理的具体应用,可以参考相关技术文档和实践案例。

    上一篇:java操作List
    下一篇:Java推动老年人社区服务(毕设源码+mysql+lw)

    发表评论

    最新留言

    很好
    [***.229.124.182]2025年05月10日 04时24分16秒

    关于作者

        喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
    -- 愿君每日到此一游!

    推荐文章

    10条sql语句优化的建议 2023-01-24
    10款宝藏编程工具!新手必备,大牛强烈推荐! 从零基础到精通,收藏这篇就够了! 2023-01-24
    10款最佳免费WiFi黑客工具(附传送门)零基础入门到精通,收藏这一篇就够了 2023-01-24
    15个Python数据分析实用技巧(非常详细)零基础入门到精通,收藏这一篇就够了 2023-01-24
    15个备受欢迎的嵌入式GUI库,从零基础到精通,收藏这篇就够了! 2023-01-24
    15个程序员常逛的宝藏网站!!从零基础到精通,收藏这篇就够了! 2023-01-24
    1分钟学会在Linux下模拟网络延迟 2023-01-24
    200款免费的AI工具汇总 2023-01-24
    2023年失业的你明白了什么道理? 2023-01-24
    00后整顿职场?公司测试岗却新来了个00后卷王,3个月薪资干到20K... 2023-01-24
    2023应届毕业生找不到工作很焦虑怎么办? 2023-01-24
    2023最新版Node.js下载安装及环境配置教程(非常详细)从零基础入门到精通,看完这一篇就够了 2023-01-24
    2023网络安全现状,一个(黑客)真实的收入 2023-01-24
    2024 年需要了解的顶级大数据工具(非常详细)零基础入门到精通,收藏这一篇就够了 2023-01-24
    2024 最新 Kali Linux 定制化魔改,完整版,添加常见60渗透工具,零基础入门到精通,收藏这篇就够了 2023-01-24
    2024大模型行业应用十大典范案例集(非常详细)零基础入门到精通,收藏这一篇就够了 2023-01-24
    00后才是内卷之王,被卷的头皮发麻.... 2023-01-24
    2024届秋招让我(985本硕)直接破防,感觉书读了这么久结果毫无意义,读书就只为了读书,我该怎么办? 2023-01-24
    2024年专业介绍||现代通信技术,从零基础到精通,收藏这篇就够了! 2023-01-24
    2024年为什么越来越多的人选择转行网络安全?零基础入门到精通,收藏这篇就够了 2023-01-24