zoukankan      html  css  js  c++  java
  • Java反射(6)反射的经典应用----JDK动态代理

    目录:

    1.类和接口的区别
    2.静态获取接口的实例----接口的实现类
    3.动态获取接口的实例----动态代理

    1.类和接口的区别

    Java中classinterface的区别:

    • 可以实例化class(非abstract类);
    • 不能实例化interface

    所有interface类型的变量总是通过向上转型并指向某个实例的:

    CharSequence cs = new StringBuilder();
    

    2.静态获取接口的实例----接口的实现类
    传统编码方式流程如下:
    首先定义接口:

    public interface Hello {
        void morning(String name);
    }
    

    然后编写实现类:

    public class HelloImpl implements Hello {
        public void morning(String name) {
            System.out.println("Good morning, " + name);
        }
    }
    

    最后创建实例,转型为接口并调用:

    Hello hello = new HelloImpl();
    hello.morning("Bob");
    

    3.动态获取接口的实例----动态代理
    目的:(不编写实现类的前提下)为了获得接口的实例,并实现接口中的方法,并调用该方法。

    public class Main {
        public static void main(String[] args) {
    //1.创建一个handler。它负责接口中的方法实现
            InvocationHandler handler = new InvocationHandler() {
                @Override
    /invoke函数:代理对象;想调用的方法;方法的参数
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println(method);
                    if (method.getName().equals("morning")) {
                        System.out.println("Good morning, " + args[0]);
                    }
                    return null;
                }
            };
    //2.创建一个Proxy的instance。需要传入三个参数:接口的类加载器;要实现的接口;调用方法的handler
            Hello hello = (Hello) Proxy.newProxyInstance(
                Hello.class.getClassLoader(), // 传入ClassLoader
                new Class[] { Hello.class }, // 传入要实现的接口
                handler); // 传入处理调用方法的InvocationHandler
    
            hello.morning("Bob");
        }
    }
    
    interface Hello {
        void morning(String name);
    }
    

    在运行期动态创建一个interface实例的方法如下:

    • 定义一个InvocationHandler实例,它负责实现接口的方法调用;
    • 通过Proxy.newProxyInstance()创建interface实例,它需要3个参数:
      ** 使用的ClassLoader,通常就是接口类的ClassLoader
      ** 需要实现的接口数组,至少需要传入一个接口进去;
      ** 用来处理接口方法调用的InvocationHandler实例。
    • 将返回的Object强制转型为接口。

    动态代理实际上是JDK在运行期动态创建class字节码并加载的过程.
    把上面的动态代理改写为静态的实现类大概长这样:

    public class HelloStaticImpl implements Hello {
        InvocationHandler handler;
        public HelloDynamicProxy(InvocationHandler handler) {
            this.handler = handler;
        }
        public void morning(String name) {
            handler.invoke(//由handler去调用函数
               this,//Proxy对象
               Hello.class.getMethod("morning"),//方法名
               new Object[] { name });//方法参数
        }
    }
    

    参考
    https://www.liaoxuefeng.com/wiki/1252599548343744/1264804593397984

  • 相关阅读:
    leetcode 763 划分字母区间
    leetcode 392 判断子序列
    Leetcode 665 修改一个数成为非递减数组 (Easy)
    leetcode 605 种花问题 贪心算法
    leetcode 452 用最少数量的箭引爆气球 贪心算法
    leetcode 455 分发饼干 贪心算法
    delphi中的 CLX Application
    delphi 之DCOM应用服务器定义函数
    SqlServer 之 sp_executesql系统存储过程的介绍和使用
    delphi 之调用WinSock的API获取本机的机器名称和IP地址
  • 原文地址:https://www.cnblogs.com/JohnTeslaaa/p/12716988.html
Copyright © 2011-2022 走看看