• 举例理解JDK动态代理


    JDK动态代理

    说到java自带的动态代理api,肯定离不开反射。JDK的Proxy类实现动态代理最核心的方法:

    public static Object newProxyInstance(ClassLoader loader,
                                              Class<?>[] interfaces,
                                              InvocationHandler h)
    

    这个方法的作用:在运行时,动态创建一组指定接口的实现类对象。其中的三大参数:

    • ClassLoader loader

      • 类加载器,主要作用是用来加载类的,把.class文件加载到jvm的方法区中,形成class对象
    • Class<?>[] interfaces

      • 实现的接口列表
    • InvocationHandler h

      • InvocationHandler 是一个接口,里面有且只有一个方法invoke(Object proxy, Method method, Object[] args),后面会介绍。

    我们可以先看个简单的例子:

    public class DynamicProxyDemo {
    
        @Test
        public void test1() {
    
            ClassLoader loader = this.getClass().getClassLoader();
            Class[] classes = {Human.class, Car.class};
            InvocationHandler h = new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("来了,老弟~");
                    return null;
                }
            };
    
            Human human = (Human) Proxy.newProxyInstance(loader, classes, h);
            human.male();
            human.toString();
            human.getClass();
        }
    
    }
    
    interface Human {
        Object male();
    }
    
    interface Car {
        Object bmw();
    }
    

    ​ 输出:

    来了,老弟~
    来了,老弟~
    

    可以看到,代码并没有报错,因为Proxy.newProxyInstance(loader, classes, h)返回的对象是实现了指定接口的类对象,所以强转成Human没有问题,当调用Human对象的方法时,会执行InvocationHandler里的invoke方法的语句。但是我当我调用getClass()方法时,并没有执行对应的语句,这是由于此方法是native方法,是调用本地的方法。

    既然调用代理对象的所有方法(个别除外)都会调用某个方法(invoke()),我们可以在里面进行任意操作,达到前置或者后置增强的效果。

    以下这图可以解析invoke(Object proxy, Method method, Object[] args)方法里的参数和human接口带参数的方法之间的关系:

    输出:

    来了,老弟~
    科比
    

    此方法也包含三大参数:

    • Object proxy
      • 当前对象,即生成的代理对象
    • Method method
      • 当前被调用的方法,即目标方法
    • Object[] args
      • 方法传入的参数

    未完待续。

  • 相关阅读:
    C++如何在Dialog和View中显示梯度背景颜色
    C++MFC的关键类(View,Application,Frame,Document等等)之间访问方法列表
    C++深入分析MFC文档视图结构(项目实践)
    C++如何修改SDI程序的默认背景颜色
    BAPI使用HR_INFOTYPE_OPERATION函数批量导入HR信息纪录代码样例(0759信息类型)
    C++在单文档的应用程序增加多个视图
    SD定价过程的16个字段的作用说明
    HR上载信息类型的长文本的样例代码
    C++在工具条中加入组合框控件
    C++如何锁定splitter窗口
  • 原文地址:https://www.cnblogs.com/kobelieve/p/10441011.html
Copyright © 2020-2023  润新知