程序为什么需要代理?
当一个对象要做的事情过多,可以通过代理来转移一部分职责。
对象有什么方法想要被代理,代理就一定有对应的方法。
动态代理
动态代理它可以直接给某一个目标(被代理 对象)对象(实现了某个或者某些接口)生成一个代理对象,而不需要代理类存在。
动态代理与代理模式原理是一样的,只是它没有具体的代理类,直接通过反射生成了一个代理对象。
JDK中提供的动态代理生成
1、Java.lang.reflect.Proxy类可以直接生成一个代理对象
Proxy.newProxyInstance方法参数介绍
//参数1:
//ClassLoader:用于指定一个类加载器,通常是当前类.class.getClassLoader()
//参数2:
//Class[] interfaces:
//指定生成的代理接口的类,即需要实现哪些方法,可以接收一个或多个接口
//InvocationHandler:
//用来指定生成的代理要干什么事情
//返回值:
该方法返回object对象,需要进行强转成需要的代理对象。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
2、InvocationHandler方法参数介绍
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
invoke回调方法,是动态代理模式实现的核心。
每当创建的代理对象调用声明的接口方法时,就会去触发这个invoke回调方法,将代理对象、当前方法、和参数都回调到invoke,内部要做的事情就需要自主实现。并将该方法进行返回,invoke会返回object来作为任何方法的返回值。
Object proxy:代理对象
Method method:被代理对象当前被调用的方法(当前被调用的接口方法)
Object[] args:接口定义方法的参数数组
实战示例:
实现一个明星类可以唱歌跳舞,需要生成代理来实现准备话筒,准备场地的事情。

1.创建接口用来定义好被代理类需要代理出去的方法
public interface Star {
//接口用来定义好被代理类需要代理出去的方法
String sing(String name);
void dance(String name);
}
2.创建需要进行代理的类,并实现如上接口
public class BigStar implements Star {
//需要实现需要代理方法创建的接口Star接口,去做真实的实现
private String name;
public BigStar(String name) {
this.name = name;
}
@Override
public String sing(String song) {
System.out.println("唱一首" + song);
return "谢谢";
}
@Override
public void dance(String dance) {
System.out.println("跳一个" + dance);
}
}
3.创建代理生成类,内部实现用Proxy.newProxyInstance创建代理对象,并定义好invoke方法:
public class ProxyUtil {
//定义生成代理对象方法
//方法传入接口来定义生成哪个接口的代理,并返回实现该接口的对象
public static Star createProxy(Star bigStar) {
Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
new Class[]{Star.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//对各个调用事件进行判断分别处理
if (method.getName().equals("sing")) {
Log.i("minfo", "收钱20w");
} else if (method.getName().equals("dance")) {
Log.i("minfo", "收钱100w");
}
return method.invoke(bigStar, args); //这里再使用反射调用被代理对象的当前方法
}
});
return starProxy;
}
}
4.执行测试:
Star bigStar = new BigStar("Lisa");
Star starProxy = ProxyUtil.createProxy(bigStar);
String result = starProxy.sing("solo"); //代理来唱歌
// starProxy.dance("惊鸿舞"); //代理来跳舞
Log.i("minfo", "sing结果:" + result);
5.调用结果:

实现场景2
Retrofit进行网络请求,每当调用ApiService的某个请求方法是,会在动态代理中回调该方法,Retrofit会统一使用反射获取method所携带的请求类型注解信息,请求返回类型和泛型类型,进行对象解析,返回类型转换,并且封装成ServiceMethod,传递给okhttp进行真实请求。
参考:
https://www.bilibili.com/video/BV1ue411N7GX?p=1&vd_source=40c24e77b23dc2e50de2b7c87c6fed59