zoukankan      html  css  js  c++  java
  • Java代理笔记

    代理顾名思义,就是一个中间层,当我们要使用某个方法时,不直接调用,而是告诉代理,让代理替我们去请求方法,并返回结果。在这个过程中,我们只知道代理执行并返回给了我们操作结果,至于它有没有其他操作并不知道,但这个也无关紧要,因为不管代理在请求实际方法之前和之后做了什么,对我们都不会产生任何影响。由于代理的这个特性,可以用来进行记录日志等操作。

    代理分为静态代理动态代理

    静态代理

    静态代理需要我们在调用者和具体的执行者之间创建一个代理类,其实现需要被代理的接口并持有一个此接口,具体代码如下:

    接口类(被代理):

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

    代理类:

    public class HelloProxy implements Hello {
    ​
        private Hello helloImpl;
    ​
        public HelloProxy() {
            this.helloImpl = new HelloImpl(); // HelloImpl为一个Hello接口的一个普通实现类
        }
    ​
        @Override
        public void say(String name) {
            System.out.println("before say");
            helloImpl.say(name);
            System.out.println("after say");
        }
    }

    使用的时候只需要new一个代理类赋值给接口即可:Hello hello = new HelloProxy(),之后的执行会由代理类去负责。但是这么做有一个问题就是对每个需要代理的类,都需要创建一个对应的代理类,即使代理类的逻辑都是相似的,动态代理就是解决这个问题的。

    动态代理

    动态代理相当于在调用者和代理类之间又增加了一个中间层,在这个中间层中完成代理类的逻辑,达到复用代码的效果。这个中间层需要实现InvocationHandler接口,并持有一个被代理的类,大致代码如下:

    public class Myproxy implements InvocationHandler {
    ​
        private Object target; // 被代理的类
    public Myproxy(Object target) {
            this.target = target;
        }
    ​
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before invoke"); // 执行代理的方法前进行的操作
            Object invoke = method.invoke(target, args); // 调用执行被代理的方法
            System.out.println("after invoke"); // 执行代理的方法后进行的操作
            return invoke; // 返回方法执行结果
        }
    }

    使用时,使用Proxy的静态方法获取代理类,将其强转为对应的接口,之后可以同静态代理类同样使用。

    Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

    其中loader为类加载器,interfaces为要代理的接口,h为之前定义的实现InvocationHandler接口的类的实例。

    这个方法会返回一个代理类,其实现的要代理的接口,并持有一个实现InvocationHandler接口的实例,代理类的代码大致如下:

    public final class $Proxy0 extends Proxy
      implements Hello
    {
    ​
      public $Proxy0(InvocationHandler paramInvocationHandler) {
        super(paramInvocationHandler);
      }
    ​
      public final String say() {
        try
        {
          return ((String)this.h.invoke(this, m3, null));
        }
        catch (RuntimeException localRuntimeException)
        {
          throw localRuntimeException;
        }
        catch (Throwable localThrowable)
        {
          throw new UndeclaredThrowableException(localThrowable);
        }
      }
    ​
    }

    如上代码我们可以将其强转为Hello接口,实际调用的时候会调用InvocationHandler实现类中的invoke方法,而其中就是我们实现的代理业务,当然,也包括实际的业务。

    这样,对于有相同代理业务的类,我们只要实现InvocationHandler接口,在其中的invoke方法实现需要代理的业务,使用时只要使用Proxy.newProxyInstance静态方法,传入对应得参数即可得到需要的代理类,再将其强转赋值给需要的接口,即可正常使用。

  • 相关阅读:
    C#事件理解
    二叉排序树查找算法代码
    二叉排序树查找算法代码
    深度学习——02、深度学习入门——卷积神经网络
    深度学习——02、深度学习入门——卷积神经网络
    程序员表白代码
    程序员表白代码
    程序员表白代码
    vbs实现消息轰炸
    vbs实现消息轰炸
  • 原文地址:https://www.cnblogs.com/zawier/p/6723202.html
Copyright © 2011-2022 走看看