目录
系列文章:
Retrofit源码学习五:Retrofit中同步、异步请求解析
代理模式简介:
代理模式:为其他对象提供一种代理,用以控制对这个对象的访问。如下图所示:
静态代理:
/**
* Description:抽象对象
*/
public abstract class AbstractObject {
protected abstract void operation();
}
/**
* Description:目标对象
*/
public class RealObject extends AbstractObject {
@Override
protected void operation() {
System.out.println("do operation...");
}
}
/**
* Description:代理类
*/
public class ProxyObject extends AbstractObject {
//对目标类的引用
private RealObject realObject;
public ProxyObject(RealObject realObject) {
this.realObject = realObject;
}
@Override
protected void operation() {
System.out.println("do something before real operation...");
if (realObject == null) {
realObject = new RealObject();
}
realObject.operation();
System.out.println("do something after real operation...");
}
}
动态代理:
动态代理模式是Retrofit中一种非常重要的设计模式。也是Java中非常重要的一种特性。
特点:无侵入地增强我们的方法(在不用修改原来的代码的前提下,在已有的方法的前后,做我们想做的事情)。
定义:代理类在程序运行时创建的代理方式。也就是说,在这种动态代理模式下,代理类并不是在java代码中定义的,而是在运行时根据我们在java代码中的配置动态生成的。
相比于静态代理,动态代理的一个很大优点就是它能很方便地对我们的代理的函数进行统一处理,而不用频繁地修改每一个代理类的函数。
现在,只有两种动态代理的写法:
1、jdk动态搭理。需要客户端写辅助接口来实现。由java的内部的反射机制来实现,所以说它在生成类的过程中是比较高效的,我们主要讲的就是这种写法。主要注意的是,它只能为接口创建动态代理。
2、CGLIB动态代理。可以直接修改字节码。
InvocationHandler:
- 每个代理类的对象都会关联一个表示内部处理逻辑的InvocationHandler接口的实现
- invoke方法的参数中可以获取参数
- invoke方法的返回值被返回给使用者
代码实现:
public interface Subject {
void shopping();
}
public class Man implements Subject {
@Override
public void shopping() {
System.out.println("xxx" + "要去买东西...");
}
}
public class Proxy implements InvocationHandler {
//要代理的真实对象
private Object target;
public Proxy(Subject target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy: " + proxy.getClass().getName());
System.out.println("before...");
method.invoke(target, args);
System.out.println("after...");
return null;
}
}
public class Client {
public static void main(String[] args) {
Subject man = new Man();
Proxy p = new Proxy(man);
//通过java.lang.reflect.newProxyInstance(...)方法获得真实对象的代理对象
Subject subject= (Subject) java.lang.reflect.Proxy.newProxyInstance(
man.getClass().getClassLoader(), man.getClass().getInterfaces(),p);
//通过代理对象调用真实对象相关接口中实现的方法,这个时候就会跳转到这个代理对象所关联的handler的invoke()方法
subject.shopping();
//获得真实对象的代理对象所对应的Class对象的名称,用字符串表示
System.out.println(subject.getClass().getName());
}
}
动态代理总结:
- 运行期
- InvocationHandler接口和Proxy类
- 动态代理与静态代理最大的不同就是:动态代理的代理类是不需要我们手动生成的,是在运行时动态生成的