概述
为其他对象 提供一种代理,以控制对这个对象的访问,代理大概分为两类,静态代理和动态代理
UML 类图
静态代理##
Subject
Subject 定义了RealSubject 和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy
public interface Subject {
void request();
}
RealSubject
RealSubject 代表了Proxy所代理的真实实体
public class RealSubjiect implements Subject {
@Override
public void request() {
Log.d("mmm","调用了真实对象");
}
}
Proxy
Proxy类,保存一个真实对象的引用,使得代理可以访问实体,并实现Sunject接口,这样代理就可以代替实体
public class ProxySubject implements Subject {
private RealSubjiect mRealSubject;
public ProxySubject() {
if (mRealSubject == null) {
mRealSubject = new RealSubjiect();
}
}
@Override
public void request() {
// to do something
mRealSubject.request();
// to do something
}
}
客户端调用
//静态代理
ProxySubject proxySubject = new ProxySubject();
proxySubject.request();
动态代理
静态代理在编译期间,代理类就已经被我们写了出来,这样每一个RealSubject类都对应一个代理类,编写特别麻烦,动态代理,我们不用手动编写代理类,只要简单的指定一组接口,及委托类(真实类)对象,便能动态的获取代理类、
要实现动态代理需要借助java中的俩个接口或类,InvocationHandler(接口)和Proxy(类),简单介绍一下
InvocationHandler 接口
每个动态代理类都必须要实现InvocationHandler 这个接口,并且每一个代理类的实例都关联到了一个handler,当我们通过一个代理对象调用一个方法的时候,这个方法的调用就会被转发到InvocationHandler 这个接口的invoke方法进行调用,我么来看一下InvocationHandler 这个接口的 唯一方法invoke
invoke
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
这个方法接收三个参数,和一个返回值,意思分别为下:
proxy:指代理的对象
method:指的是我们所要调用的真实对象的方法的Method 对象
args: 指的调用方法的参数
返回的object 是指真实方法的返回值
Proxy 类
Proxy类的作用,就是用来动态的创建代理对象,我们经常使用的是newProxyInstance这个方法
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
参数理解
loader:一个ClassLoader对象,定义了由哪一个ClassLoader对象,对生成的代理类进行加载
interfaces:一个interface对象的数组,表示我将要给代理类提供一组什么样的接口
hInvocationHandler 对象,表示我动态代理对象在调用的方法的时候,会关联那个InvocationHandler 对象上
返回值,返回一个代理类
实例
public interface Subject {
void request();
}
public class RealSubjiect implements Subject {
@Override
public void request() {
Log.d("mmm","调用了真实对象");
}
}
public class ProxyHandler implements InvocationHandler {
private RealSubjiect mRealSubject;
public ProxyHandler() {
if (mRealSubject == null) {
mRealSubject = new RealSubjiect();
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//before
Object result = method.invoke(mRealSubject, args);
//after
return result;
}
}
//动态代理
//创建调用处理器对象
ProxyHandler proxyHandler = new ProxyHandler();
//动态生成代理对象
Subject proxy = (Subject) Proxy.newProxyInstance(RealSubjiect.class.getClassLoader(), RealSubjiect.class.getInterfaces(), proxyHandler);
//调用方法
proxy.request();
如何动态创建的代理类
newProxyInstance 他内部主要做了这几项工作,生成的代理类对象
static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler handler)
{
//1. 根据类加载器和接口创建代理类
Class clazz = Proxy.getProxyClass(loader, interfaces);
//2. 获得代理类的带参数的构造函数
Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class });
//3. 创建代理对象,并制定调用处理器实例为参数传入
Interface Proxy = (Interface)constructor.newInstance(new Object[] {handler});
}
代理类调用方法是如何转发到InvocationHandler的invoke方法的
动态生成的代理类,大概是这个样子的
public final class $Proxy1 extends Proxy implements Subject{
private InvocationHandler h;
private $Proxy1(){}
public $Proxy1(InvocationHandler h){
this.h = h;
}
public int request(int i){
Method method = Subject.class.getMethod("request", new Class[]{int.class}); //创建method对象
return (Integer)h.invoke(this, method, new Object[]{new Integer(i)}); //调用了invoke方法
}
}
他有以下几个特点
1 继承了Proxy接口,实现了Proxy.newProxyInstance中提供接口数组
2 是public final的
3 命名方式为 $ProxyN,其中N会慢慢增加,一开始是
P
r
o
x
y
1
,
接
下
来
是
Proxy1,接下来是
Proxy1,接下来是Proxy2…
4 有一个参数为 InvocationHandler 的构造函数。这个从 Proxy.newProxyInstance() 函数内部的clazz.getConstructor(new Class[] { InvocationHandler.class }) 可以看出。
我是怎么知道的?
参考https://www.cnblogs.com/gonjan-blog/p/6685611.html
https://www.cnblogs.com/huhx/p/dynamicTheoryAdvance.html