博客
关于我
Java提高班(六)反射和动态代理(JDK Proxy和Cglib)
阅读量:790 次
发布时间:2023-01-24

本文共 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反射与动态代理的具体应用,可以参考相关技术文档和实践案例。

    转载地址:http://bleyk.baihongyu.com/

    你可能感兴趣的文章
    Servlet的三个基本方法
    查看>>
    基于Trae AI的新SSH Remote功能:服务器Python接口日志排查实战与技术展望
    查看>>
    反 TypeScript
    查看>>
    数据分析与处理方法
    查看>>
    打开有惊喜
    查看>>
    AUTOSAR_SWS_CANDriver4
    查看>>
    程序员都看不懂的代码
    查看>>
    LLM+多智能体协作:基于CrewAI与DeepSeek的邮件自动化实践
    查看>>
    404页面自动跳转源码
    查看>>
    458. 可怜的小猪
    查看>>
    46:把数字翻译成字符串(动态规划)
    查看>>
    49天精通Java,第28天,Java lambda表达式
    查看>>
    500套精美Logo样机模板可直接套用、轻松制作炫酷logo
    查看>>
    5小时内使用DeepSeek写出一篇优质论文的三步攻略指南
    查看>>
    60天新媒体公众号写作秘诀
    查看>>
    ASP.NET MVC4 json序列化器
    查看>>
    Android 版本更新之打开apk文件的前生今世
    查看>>
    64位WIN7+oracle11g+plsql安装
    查看>>
    70. 爬楼梯
    查看>>
    7B2 PRO主题5.4.2免授权直接安装
    查看>>