Java基础相关

JAVA基础-动态代理

2021-01-06  本文已影响0人  来lol里
image.png

我们先看下静态代理,具体方法就是创建一个接口,然后创建被代理的类实现该接口并且实现该接口中的抽象方法。之后再创建一个代理类,同时也需要实现这个接口。在代理类中会持有一个被代理对象的引用,而后在代理类方法中调用该对象的方法。静态代理被代理类和代理类是一对一的关系,这就造成了如果需要被代理的类多了,那相应的代理类也会很多,那这就很不程序猿了。这时候动态代理就粗线了(此处有掌声),和静态代理相比,动态代理就是代理类这块由系统通过底层反射的方式帮我们生成了(这就很程序猿了),但是和静态的思路是一样的,具体看一下静态代理的例子

先创建一个接口

    String buy();
}

搞两个被代理的类,继承这个接口

public class ZhangSan implements IBuySth {
    @Override
    public String buy() {
        System.out.println("我张三要买东西的");
        return "";
    }
}
public class LiSi implements IBuySth {
    @Override
    public String buy() {
        System.out.println("我李四要买东西的");
        return "";
    }
}

然后我们就可以搞个代理类了

public class Seller implements IBuySth {
    IBuySth iBuySth;

    public Seller(IBuySth iBuySth) {
        this.iBuySth = iBuySth;
    }

    @Override
    public String buy() {
        System.out.println("Before buy " );
        iBuySth.buy();
        System.out.println("After buy " );
        return "";
    }
}

我们去调用一下这个代理类

        IBuySth san=new ZhangSan();
        Seller seller=new Seller(san);
        seller.buy();

我们看一下结果,是没问题的。-代理模式就是自己要做的事,通过其他实现相同接口的类去代替完成-,就是这么个意思。


image.png

静态代理完了,再看一下我们的动态代理类,这个类首先要传入被代理对象,这里用object就可以,然后要实现的就是InvocationHandler这个接口,通过这个接口重载的invoke方法,在这个方法里我们可以在调用被代理对象之前和之后做一些方法,这也是动态代理的优势可扩展性,然后调用method方法的invoke,其实这个底层就是用的反射的方式去获取被代理对象的那个buy方法,然后对外部暴露一个getInstance方法,这个写在外边也ok的,这个方法主要是通过Proxy这个类去反射出我们的代理类,如果打断点就会发现其实就是Proxy0、Proxy1这些系统帮我们生成的代理类。

public class MyProxy implements InvocationHandler {
    Object obj;

    public MyProxy(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before invoke "  + method.getName());
        method.invoke(obj,args);
        System.out.println("After invoke " + method.getName());
        return null;
    }
    public Object getInstance(){
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);

    }
}

最后我们可以去调用一下了

      IBuySth san=new ZhangSan();//此处改外new LiSi则调用的被代理对象就是李四了
        MyProxy myProxy=new MyProxy(san);
       Proxy.newProxyInstance(san.getClass().getClassLoader(), san.getClass().getInterfaces(), handler);
        IBuySth s= (IBuySth) myProxy.getInstance();
        s.buy();

可以看到和静态代理结果是一样的


image.png

动态代理被广泛的用在各种框架中,虽然我们代码中遇到的少,但是还是要掌握的,比如Retrofit的 cteate方法中,可以看到就是用到了动态代理的方法去实现的。

  public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() { //动态代理的方法去实现的
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, Object... args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod serviceMethod = loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }
上一篇 下一篇

猜你喜欢

热点阅读