栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

设计模式之代理模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

设计模式之代理模式

代理模式分为静态代理和动态代理 静态代理

就拿网络请求来说
先定义一个网络请求统一接口INetworkRequester 里面有一个post方法

public interface INetworkRequester{
	void post();
}

网络请求框架有很多种比如早期的 Volley 现在的Okhttp

public class OkhttpNetworkRequester implements INetworkRequester{
	public void post(){
		Log.i("ancely_proxy","OkhttpNetworkRequester.post()");
	}
}

public class VolleyNetworkRequester implements INetworkRequester{
	public void post(){
		Log.i("ancely_proxy","VolleyNetworkRequester.post()");
	}
}

在请求网络的时候有一个代理的网络请求器,在请求网络的时候我们并不关心里面是怎么请求的,只要能达到目的就可以

public class ProxyNetworkRequester implements INetworkRequester{
	private INetworkRequester mRequester;
	public ProxyNetworkRequester(INetworkRequester requester){
		mRequester = requester;
	}
	public void post(){
		mRequester.post();
	}

}

假如我们一开始使用的是Volley请求库,我们只需要这样调用

INetworkRequester requester = new ProxyNetworkRequester(new VolleyNetworkRequester());
requester.post();//这样用的就是Volley框架

//后面更新迭代,Volley不受欢迎,Okhttp流行起来了我们要换库就非常的方便
INetworkRequester requester = new ProxyNetworkRequester(new OkhttpNetworkRequester());
requester.post();//这样用的就是Okhttp框架

当然比如常用的Json序列化库也可以同样操作

动态代理

动态代理使用起来其实很简单,主要是调用Proxy的newProxyInstance方法

INetworkRequester requester = new ProxyNetworkRequester(new VolleyNetworkRequester());
Object proxyInstance = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{INetworkRequester.class}, (o, method, objects) -> {
    Log.i("ancely_proxy","newProxyInstance.post()");
    return method.invoke(requester,objects);
});
INetworkRequester requester1 = (INetworkRequester) proxyInstance;
Log.i("ancely_proxy","proxyInstance hashCode: ."+ requester1.hashCode());
requester1.post();
动态代理原理
  • 类的完整生命周期
    Java源文件---->编译生成java字解码.class文件(实实在在的文件)---->通过类加载机制变成Class对象----->然后再实例化出对象—>卸载

  • 动态代理的class对象是怎么来的

    • 逻辑在Proxy的newProxyInstance里
    • 通过Proxy里的getProxyClass0方法创建了一个Class对象cl,怎么生成的我们不关心
    • 获取Class对象的构造方法cl.getConstructor(constructorParams);
    • 反射创建对象cons.newInstance(h);h就是我们newProxyInstance方法里传进定数的InvocationHandler接口
      源码如下
private static final Class[] constructorParams = new Class[]{InvocationHandler.class};
public static Object newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h) {
        Objects.requireNonNull(h);
        final Class[] intfs = interfaces.clone();
        //创建了一个Class对象
        Class cl = getProxyClass0(loader, intfs);
        try {
        		//获取到构造方法
            final Constructor cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                cons.setAccessible(true);
            }
            //通过构造方法实例出对象,
            return cons.newInstance(h);
        } catch (Exception e) {
            throw new InternalError(e.toString(), e);
        } 
    }

内存中生成的Class是什么样的,通过以下方法可以获取

String name = INetworkRequester.class.getName() + "$Proxy0";
byte[] bytes = ProxyGenerator.generateProxyClass(name, new Class[]{INetworkRequester.class});
try {
    FileOutputStream fos = new FileOutputStream("complier/" + name + ".class");
    fos.write(bytes);
    fos.close();
} catch (Exception e) {
    e.printStackTrace();
}
package com.ancely.complier;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class INetworkRequester$Proxy0 extends Proxy implements INetworkRequester {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0;
    public INetworkRequester$Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }
    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }
    public final void post() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }
    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m3 = Class.forName("com.ancely.complier.INetworkRequester").getMethod("post");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

通过上面文件就非常清楚动态代理的原理了

  • 1.通过Proxy.newProxyInstance创建了一个Object对象 proxyObject
  • 2.通过生成的文件可以发现 proxyObject是继承了Proxy 实现了代理接口INetworkRequester
  • 3.在生成的Class文件的构造方法中传入了我们在newProxyInstance方法中传入了InvocationHandler参数,
  • 4.所以生成的Class文件执有了一个InvocationHandler h
  • 5.当我们调用了proxyObject对应的方法时就会调用InvocationHandler h的invoke方法
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/322430.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号