美文网首页Java基础相关
JAVA基础-动态代理

JAVA基础-动态代理

作者: 来lol里 | 来源:发表于2021-01-06 13:27 被阅读0次
    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);
              }
            });
      }
    

    相关文章

      网友评论

        本文标题:JAVA基础-动态代理

        本文链接:https://www.haomeiwen.com/subject/txpnoktx.html