• java有关静态代理及动态代理的实现


    
    

    引言:

    代理是基本的设计模式之一,它为你提供额外的或不同的操作而插入的用来代替实际对象的对象(委托对象)。这些对象通常涉及到与实际对象的通信,因此代理通常充当中间人的角色。--JAVA编程思想

    相关的类和接口

    要了解 Java 动态代理的机制,首先需要了解以下相关的类或接口:

    • java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
      清单 1. Proxy 的静态方法
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      // 方法 1: 该方法用于获取指定代理对象所关联的调用处理器
      static InvocationHandler getInvocationHandler(Object proxy)
       
      // 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
      static Class getProxyClass(ClassLoader loader, Class[] interfaces)
       
      // 方法 3:该方法用于判断指定类对象是否是一个动态代理类
      static boolean isProxyClass(Class cl)
       
      // 方法 4:该方法用于为指定类装载器一组接口及调用处理器生成动态代理类实例
      static Object newProxyInstance(ClassLoader loader, Class[] interfaces,
          InvocationHandler h)
    • java.lang.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。
      清单 2. InvocationHandler 的核心方法
      1
      2
      3
      // 该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象
      // 第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行
      Object invoke(Object proxy, Method method, Object[] args)

      每次生成动态代理类对象时都需要指定一个实现了该接口的调用处理器对象(参见 Proxy 静态方法 4 的第三个参数)。

    • java.lang.ClassLoader:这是类装载器类,负责将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy 静态方法生成动态代理类同样需要通过类装载器来进行装载才能使用,它与普通类的唯一区别就是字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中

      每次生成动态代理类对象时都需要指定一个类装载器对象(参见 Proxy 静态方法 4 的第一个参数)

    这里有几点需要重点强调一下:

    • 从定义的方法可以看出代理类的出现是为了更加灵活的控制委托类方法的调用,而且做到无倾入;最终实现了一部分自己的逻辑后还是会调用委托类的方法调用,只不过在委托类调用之前或之后多了种控制
    • 未指定代理类的非限定名称。但是,以字符串 "$Proxy" 开头的类名空间应该为代理类保留
    • static Object newProxyInstance(ClassLoader loader, Class[] interfaces,
          InvocationHandler h)该生成的动态代理类实例中,类装载器需要说明的是它和静态代理的区别,静态代理是编译阶段实现已经确定的代理类的.class文件已经生成。但动态代理是字节码是由JVM在运行态动态生成的。
    以下是笔者实现的代码DEMO;供参考:

    /**
    *先是静态代理
    */
    public
    interface MyInterface { void doSomeThing(); void someThingElse(String param); }
    public class RealObject implements MyInterface{
    
        @Override
        public void doSomeThing() {
            // TODO Auto-generated method stub
            print("开始调用doSomeThing方法");
            
        }
    
        @Override
        public void someThingElse(String param) {
            // TODO Auto-generated method stub
            print("开始调用somethingelse 方法;参数"+param);
            
        }
    
    }
    public class SimpleProxy implements MyInterface{
        
        private MyInterface myInterface;
        
        
        public SimpleProxy(MyInterface myInterface) {
            this.myInterface=myInterface;
        }
    
        @Override
        public void doSomeThing() {
            // TODO Auto-generated method stub
            print("业务逻辑dosomething...");
            myInterface.doSomeThing();
            
        }
    
        @Override
        public void someThingElse(String param) {
            // TODO Auto-generated method stub
            print("业务逻辑ELse...");
            myInterface.someThingElse(param);
            
        }
        
        public static void consumer(MyInterface myInterface) {
            
            myInterface.doSomeThing();
            myInterface.someThingElse("bubu..");
        }
        
        public static void main(String[] args) {
            consumer(new RealObject());
            consumer(new SimpleProxy(new RealObject()));
        }
    
    }

    /**

    *动态代理

     */

    自定义一个调用处理器:

    /**
     * 调用处理器<P>
    *  动态代理能把所有调用都重定向到调用处理器上
    */
    public class DynamicProxyHandle implements InvocationHandler{
    
        private Object proxied;
        
        public DynamicProxyHandle(Object object) {
            this.proxied=object;
        }
        
        @Override
        public Object invoke(Object proxy,Method method,Object[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            print("proxy class:"+proxy.getClass()+" method:"+method+" args:"+args);
            
            if(method.getName().equals("doSomeThing")) {
                print("代理检测到doSomeThing被调用");
            }
    //        if(args!=null) {
    //            for(Object object:args) {
    //                print("====="+object);
    //            }
    //        }
            
            
            
            return method.invoke(proxied, args);
        }
    
    }
    public class SimpleDynamicProxy {
    
        public static void consumer(MyInterface myInterface) {
    
            myInterface.doSomeThing();
            myInterface.someThingElse("bubu..");
        }
    
        public static void main(String[] args) {
            RealObject realObject = new RealObject();
    
            consumer(realObject);
            print("-----------------------------------------");
            /**
             * 1.一个类加载器【你通常可以从已经被加载的类对象中获取得到其类加载器,然后传递给它】
             * 2.希望该代理实现的接口列表【不是类或抽象类】
             * 3.以及InvocationHandler的一个实现(一个调用处理器)
             */
            MyInterface dynamicProxy = (MyInterface) Proxy.newProxyInstance(MyInterface.class.getClassLoader(),
                    new Class[]{MyInterface.class}, new DynamicProxyHandle(realObject));
            consumer(dynamicProxy);
    
        }
    }
  • 相关阅读:
    Win10下访问linux的ext4分区文件并拷贝
    Zsh 无法找到自己的anaconda python
    Motrix 代替迅雷下载 aria2的配置
    Bash与python混合编程
    如何在 非系统盘安装 wsl
    Python_01
    CC2541蓝牙学习——通用I/O口中断
    自定义弹窗
    使用windbg搜索命令辅助逆向杀软穿透驱动注册表操作
    IAT Hook
  • 原文地址:https://www.cnblogs.com/zhangfengshi/p/9367787.html
Copyright © 2020-2023  润新知