之前有一篇设计模式的文章说过了代理模式。这一篇是对之前的补充跟深入。
1 为什么需要学习动态代理
1.动态代理能够增加程序灵活度,如加入 方法执行前后判断
2 完美解决解耦问题,动态代理可以将调用层与实现层分离,如Retorfit网络请求
3 动态代理不需要接口的实现类,如 适用于 IPC进程通信,将方法调用转成其他逻辑1.动态代理不需要接口的实现类,如 适用于 IPC进程通信,将方法调用转成其他逻辑
4 动态代理可以解决 程序执行流程,如今天讲的事件转到activity执行
动态代理含义
1定义:给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用
2目的: (1) 通过引入代理对象的方式来间接访问目标对象,防止直接访问目标对象给系统带来的不必要复杂性
为什么会有动态代理
传统面向对象思想中,如果想要实现功能复用,要么继承、要么引用,无论哪种方式,对代码都有一定的侵入性,耦合无可避免
侵入性含义:如果你想要用它增强你程序的功能,你必须改动你的程序代码,那它就具有侵入性。如果只有一点两点需要增强还好说,如果大量的功能点需要被增强,工作量就会很大,代码也不太优雅。想象一下,如果你对外公开了一系列的接口,现在领导说了,接口要加权限控制。在哪加?最笨的当然就是写个程序验证的逻辑,然后每个接口都拿来调用一遍。这也正是面向对象思想的短板,在要为程序新增一些通用功能时,只能通过耦合的方式才能进行。AOP正是为此而生,AOP旨在通过一种无耦合的方式来为程序带来增强。而动态代理就是AOP实现方式中的一种.
动态代理应用场景
Android中动态代理有哪几种实现方式
2 Proxy动态代理如何实现代理
核心原理:编译时 ,代理对象的class并不存在,当需要调用Proxy.newProxyInstance时,会构建一个Proxy0的class字节码,并且加载到内存。
byte[] bytes = ProxyGenerator.generateProxyClass("DavidHelloImpl", new Class[]{HelloInterface.class});
3 ProxyGenerator如何生成一个Class文件
ProxyGenerator:能能够在运行时生成一个对象,而这个对象是实现了该接口,这个对象所属的类是一个全新的class。 Class需要生成才能加载。而ProxyGenerator在运行时,是做生成class字节码。
可以看到这里生成了一个${name}.class ,那么name是哪里传来的。我们继续跟踪Proxy类中的
defineProxyClass方法。
从这里标记的可以看到name的命名。是不是很熟悉,$proxy。
这里我们看下手动调用ProxyGenerator,生成class 文件输入到文本看下class内部。
byte[] bytes = ProxyGenerator.generateProxyClass("HelloImpl", new Class[]{HelloInterface.class});
File file = new File("C:\\Users\\Administrator\\Downloads\\Proxy\\proxy\\src\\main\\java\\com\\maniu\\proxy\\HelloImpl.class");
FileOutputStream outputStream = new FileOutputStream(file);
outputStream.write(bytes);
outputStream.flush();
outputStream.close();
生成看到内部实现接口中的方式,是调用h.invoke()方法。
从上可知,h就是InvocationHandler
HelloInterface helloInterface= (HelloInterface) Proxy.newProxyInstance(hello.getClass()
.getClassLoader(),
hello.getClass().getInterfaces(),
new ProxyHandler(hello));
static class ProxyHandler implements InvocationHandler {
// 代理对象 张三
private Object object;
public ProxyHandler(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(object, args);
return null;
}
}
所以在调用调用代理类内部的方法后,会执行ProxyHandler 内部的invoke()方法。