欲理解动态代理,可能先了解静态代理更容易理解.
一,静态代理
从静态代理UML图可以看到,主要有三个角色:共同接口,代理对象和被代理对象(真实对象),代理对象和真实对象都继承自共同的接口.同时,代理对象拥有真实对象的引用.
//共同的接口
public interface Subject {
void operate1();
void operate2(String str);
}
//被代理对象(真实对象)
public class RealSubject implements Subject {
@Override
public void operate1() {
System.out.println("this is operate1");
}
@Override
public void operate2(String str) {
System.out.println("this is operate2 with args: "+str);
}
}
//代理对象
public class ProxySubject implements Subject {
private Subject realSubject; //此处应为接口--面向接口
public ProxySubject(Subject realSubject) {
this.realSubject = realSubject;
}
@Override
public void operate1() {
//代理对象将方法调用转发给真实对象
realSubject.operate1();
}
@Override
public void operate2(String str) {
realSubject.operate2(str);
}
}
//客户类
public class ProxyClient {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
ProxySubject proxySubject = new ProxySubject(realSubject);
//表面上是代理类操作自己的方法,实际上是将方法调用转发给了真实对象
proxySubject.operate1();
}
}
二,动态代理
所谓静态和动态指的是,接口方法的调用方式.静态代理,是真实对象显式地方法调用,而动态代理则是通过反射的方式调用真实对象的方法.
public class DynamicProxy implements InvocationHandler {
// 这个就是我们要代理的真实对象
private Object subject;
// 构造方法,给我们要代理的真实对象赋初值
public DynamicProxy(Object subject) {
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(subject, args);
}
}
public class ProxyClient {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
InvocationHandler handler = new design.pattern.structure.proxy.demo.DynamicProxy(realSubject);
Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);
subject.operate1();
subject.operate2("hello proxy");
}
}
三大角色:接口类,真实对象,InvocationHandler的实现类
通过Java的Proxy.newProxyInstance的方法调用,给Subject生成了一个实例对象;接口方法的调用,会传递给handler中,handler通过invoke的执行,间接地调用了真实对象的方法.
三,安卓中的应用
很典型的一个动态代理应用是Retrofit框架
public <T> T create(final Class<T> service) {
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
这是为Service任一个接口方法创建一个Call,用这个Call代表Http请求.
GitHub github = retrofit.create(GitHub.class);
Call<List<Contributor>> call = github.contributors("square", "retrofit");
四,代理模式的好处?
谈谈您的看法