Retrofit 动态代理详解。
代理
代替别人,去做我们想做的事情。
代理模式:为其他对象提供一种代理,用以控制对这个对象的访问。
eg:海外购物。过程有朋友在海外购买,最终结果是收到商品,只在意结果 不在意购买过程。
1.静态代理
抽象对象 AbstractObject 有 operation()接口。
代理对象 ProxyObject 有 operation()方法,且持有realObject对象的引用。
真实对象 RealObject 有 operation()方法。
代理对象,将客户端的调用,委派给了目标对象RealObject,
在调用目标对象之前和之后,都可以添加某些特定操作。
可对产生的结果进行一定的控制。
// 1.代理的抽象类,要被代理类和 目标类 需要共同继承。
public abstract class AbstractObject { //【抽象类】。
//抽象方法。共同抽象接口
protected abstract void operation();
}
//2.目标对象的实现类,继承自AbstractObject 抽象类。
public class RealObject extends AbstractObject {
@Override
protected void operation() {
System.out.println("do operation...");
}
}
//3.----静态代理,代理类角色----
public class ProxyObject extends AbstractObject {
// 3.0 对目标类的引用,有统一的接口。可以在任何时候替换目标对象。
private RealObject realObject;
public ProxyObject(RealObject realObject) { //替换目标类
this.realObject = realObject;
}
@Override
protected void operation() { //代理自己的operation
//3.1 在调用目标对象前面添加东西。可以加自己的判断逻辑
System.out.println("do something before real peration...");
if (realObject == null) {
realObject = new RealObject();
}
//3.2 委派给了目标对象。调用目标对象的方法。
realObject.operation();
//3.3 在调用目标对象后面添加东西。可以加自己的判断逻辑
System.out.println("do something after real operation...");
}
}
public class Test {
public static void main(String[] args) {
// 最终对象
RealObject realObject = new RealObject();
// 代理对象
ProxyObject proxyObj = new ProxyObject(realObject);
proxyObj.operation();
}
}
//最终输出:
// do something before real peration...
// do operation...
// do something after real operation...
使用场景:
对已有方法做改进,故建议修改原有的方法,可以使用静态代理。
可以采用代理类,调用原来的方法,对产生的结果进行控制。
使用代理模式,能将功能划分的更加清晰,让代码维护更加便捷。
2.动态代理【重要】【为接口创建代理】
优势:‘无侵入’式的拓展代码,增强一些方法和功能。在方法的前后,可以做任何想做的事情。
动态代理: 代理类在程序运行时,创建的代理方式。
相比于静态代理:
优势,他能很方便的对代理类的函数,进行统一的处理。而不用频繁的去修改每一个代理类的函数。
两种动态代理:jdk动态代理(java内部的反射机制,生成类的过程中高效); CGLIB动态代理.
在不改变原来代码的情况下,在调用的前后添加代码。
jdk中的代理,只能为接口创建代理。
2.0 拦截
1.每个代理类的对象都会关联一个表示内部处理逻辑的 InvocationHandler 接口的实现;
当使用者调用了代理对象所代理的接口中的方法时,这个调用的信息 就会传递到 InvocationHandler的invoke方法;
2.invoke方法的参数中 可以获取参数(3个参数)
3.invoke方法的返回值 将返回给使用者。
2.1 代码部分
//1. 抽象接口类
public interface Subject{
void shopping();
}
//2.目标类
public class Man implements Subject {
@Override
public void shopping() {
System.out.println("Mjj"+"要去买东西...");
}
}
//3.代理类。继承自InvocationHandler,并实现其invoke方法。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class Proxy implements InvocationHandler {
private Object target;//要代理的真实对象
public Proxy(Subject target){
this.target = target;
}
//代理对象调用程序的时候,所一定要实现的接口,当通过代理对象调用方法的时候,
//这个方法就会把它指派到它调用处的 InvocationHandler的invoke 方法上.
//proxy 指代的真实对象,可理解为真实对象的一个代理;
//method 真实对象的方法;
//args 所代理真实对象的 某个方法的 所有参数.
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;
}
}
//4.测试类
public class Client {
public static void main(String[] args) {
Subject man = new Man();
Proxy p = new Proxy(man);
//4.1 【重点】通过java.lang.reflect.newProxyInstance(...)方法获得真实对象的代理对象
//-类加载器,把动态生成的代理的字节码文件加载到jvm虚拟机当中。一般使用被代理类的类加载器。
//-getInterfaces() 为代理对象提供的接口,就是被代理实现的接口;
// public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
//-p:当代理对象调用方法的时候,关联到InvocationHandler,然后调用里面的 invoke方法。
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());
}
}
// Proxy中,关联InvocationHandler
public class Proxy implements java.io.Serializable {
/**
* the invocation handler for this proxy instance.
*/
protected InvocationHandler h;
}
Subject subject = (Subject)java.lang.reflect.Proxy.newProxyInstance(man.getClass().getClassLoader(),
man.getClass().getInterfaces(), p);
// 根据传递的class对象,生成对象A(代理类),每当代理A执行某个方法的时候,
他就会调用第三个参数 InvocationHandler 的invoke() 方法。
在这个方法中,可以执行响应的操作。 这就是jdk动态代理的全过程。
总结:
1.运行期,动态代理 他是通过代理类与相关接口不直接发生联系的情况下,而在运行时实现动态关联;
2.InvocationHandler 接口 与 Proxy类(反射包中)。
3.动态代理与静态代理最大的不同:动态代理的代理类,不需要手动生成,
该代理类是根据配置在运行期间动态生成的(不是hardCode,是运行期动态生成的)。
这个动态生成的代理类,已经实现了代理对象的相关接口,
----------End------------------------








网友评论