一、代理模式
代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。
二、静态代理
静态代理的代理类持有被代理者的引用,在方法调用时,代理对象调用了被代理对象去执行真正的实现。
2.1 简单示例
假如对于一个日志处理功能,可通过代理类代理实例日志处理类:
// 1.首先定义接口层
interface ILogProcessor {
public void printLog(String log);
}
// 2.定义实现类
public class MainLogProcessor implements ILogProcessor {
@Override
public void printLog(String log) {
Log.d("LogProcessor", "MainLogProcessor" + log);
}
}
// 3.定义代理类
public class LogProcessorProxy implements ILogProcessor {
// 代理类持有被代理类的引用
private ILogPrinter mainLogProcessor = new MainLogProcessor();
@Override
public void printLog(String log) {
// 代理类需要完成的一些额外处理
Log.d("LogProcessor", "ProxyLogProcessor" + log);
String finalLog = Thread.currentThread() + log;
mainLogPrinter.printLog(finalLog);
}
}
这样,在使用过程中,可以按如下方式使用:
public void main() {
String log = "important log";
ILogPrinter proxy = new LogPrinterProxy();
proxy.printLog(log);
}
2.2 AIDL
AIDL中也用到了代理模式,在Android Studio中新建一个AIDL文件,如下所示:
// IMyAidlInterface.aidl
package com.bc.sample;
interface IMyAidlInterface {
void testFun();
}
在点击make project后,会自动生成AIDL接口对应的代码,即对应的Stub和Proxy,可以看到AIDL的Proxy是通过静态代理实现,自动生成的代码如下所示:
package com.bc.sample;
// Declare any non-default types here with import statements
public interface IMyAidlInterface extends android.os.IInterface
{
/** Default implementation for IMyAidlInterface. */
public static class Default implements com.bc.sample.IMyAidlInterface
{
@Override public void testFun() throws android.os.RemoteException
{
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.bc.sample.IMyAidlInterface
{
private static final java.lang.String DESCRIPTOR = "com.bc.sample.IMyAidlInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.bc.sample.IMyAidlInterface interface,
* generating a proxy if needed.
*/
public static com.bc.sample.IMyAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.bc.sample.IMyAidlInterface))) {
return ((com.bc.sample.IMyAidlInterface)iin);
}
return new com.bc.sample.IMyAidlInterface.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_testFun:
{
data.enforceInterface(descriptor);
this.testFun();
reply.writeNoException();
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
// 主要关注代理模式的实现;可以看到AIDL的Proxy是通过静态代理模式实现
private static class Proxy implements com.bc.sample.IMyAidlInterface
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public void testFun() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_testFun, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().testFun();
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
public static com.bc.sample.IMyAidlInterface sDefaultImpl;
}
static final int TRANSACTION_testFun = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
public static boolean setDefaultImpl(com.bc.sample.IMyAidlInterface impl) {
// Only one user of this interface can use this function
// at a time. This is a heuristic to detect if two different
// users in the same process use this function.
if (Stub.Proxy.sDefaultImpl != null) {
throw new IllegalStateException("setDefaultImpl() called twice");
}
if (impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
return false;
}
public static com.bc.sample.IMyAidlInterface getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
}
public void testFun() throws android.os.RemoteException;
}
三、动态代理
在2.1的静态代理代码中,如果现在需要扩展一个新的接口,那就需要分别在接口层、实际处理类、代理类中分别改动,如下所示:
// 1.首先定义接口层
interface ILogSender {
public void sendLog(String log);
}
// 2.定义实现类
public class MainLogSender implements ILogSender {
@Override
public void sendLog(String log) {
Log.d("LogSender", "MainLogSender send" + log);
}
}
// 3.定义代理类
public class LogSenderProxy implements ILogSender {
// 代理类持有被代理类的引用
private ILogSender mainLogSender = new MainLogSender();
@Override
public void sendLog(String log) {
// 代理类需要完成的一些额外处理
Log.d("LogSender", "ProxyLogSender" + log);
String finalLog = Thread.currentThread() + log;
mainLogSender.sendLog(finalLog);
}
}
当代理一个新的接口时可见,新的代理类与其他代理类代码是高度相似的,因此可以采用动态代理的方式来完成类似的功能。
3.1 基础用法
与静态代理不同,动态代理类的class是在运行过程中动态生成的。
3.1.1 基础用法
首先定义接口层:
// 定义接口层
interface ILogProcessor {
public void printLog(String log);
}
然后使用Proxy.newProxyInstance完成动态代理如下:
private void main() {
ILogProcessor proxy = (ILogProcessor) Proxy.newProxyInstance(this.getClassLoader(), new Class<?>[] {ILogPrinter.class}, new InvocationHandler() {
/**
* @param proxy 代理对象
* @param method 被调用的方法
* @param args 被调用的方法的参数列表
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
String log = (String)args[0];
Log.d("LogProcessor", "ProxyLogProcessor" + log);
String finalLog = Thread.currentThread() + log;
Log.d("LogProcessor", "printLog" + finalLog);
return null;
}
});
proxy.printLog("");
}
其中,InvocationHandler就是将静态代理中需要实现的部分抽离了出来,即动态生成的Proxy代理了InvocationHandler。
3.1.2 动态生成的class
动态生成的代理类的方法实际调用都到了InvocationHandler的invoke方法,动态生成的代理类class伪代码如下:
public final class $Proxy0 extends Proxy implements ILogProcessor {
static {
m3 = Class.forName("com.bc.sample.ILogProcessor").getMethod("printLog");
}
private static Method m3;
public void printLog(String log) {
// 实际调用到了InvocationHandler的invoke方法
super.h.invoke(this, m3, (Object[])log);
}
}
3.1.3 源码分析
下面分析Proxy.newProxyInstance的源码:
public class Proxy implements java.io.Serializable {
// 动态生成的class的缓存;ProxyClassFactory可动态生成代理class
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
// 生成代理class并返回对应的实例
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
// 查找或动态生成代理类的class
Class<?> cl = getProxyClass0(loader, intfs);
// 获取动态代理类的构造函数
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
cons.setAccessible(true);
}
// 通过反射调用构造函数返回代理类的实例;参数中的InvocationHandler对象作为参数传递给类构造函数;
return cons.newInstance(new Object[]{h});
}
// 获取动态代理类class
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
return proxyClassCache.get(loader, interfaces);
}
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?
{
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";
// WeakCache.get()会调用到apply,最终调用generateProxy生成动态代理类class
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
// ....
return generateProxy(proxyName, interfaces, loader, methodsArray,
exceptionsArray);
}
}
// 动态生成代理类class
private static native Class<?> generateProxy(String name, Class<?>[] interfaces,
ClassLoader loader, Method[] methods,
Class<?>[][] exceptions);
}
3.2 Retrofit动态代理
Retrofit是一个开源网络库,其源码中也使用到了动态代理模式。简单介绍如下:
3.2.1 基础用法
首先,新建网络请求对应的接口:
public interface SampleRequestInterface {
@HTTP(method = "GET", path = "/api", hasBody = true)
Call<BaseResponse> getCall();
}
然后,使用Retrofit动态代理生成请求:
public class MainActivity {
private void sendRequest() {
try {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://graph.baidu.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
// 返回请求接口的代理类实例,内部实现是用动态代理实现
SampleRequestInterface sampleRequest = retrofit.create(SampleRequestInterface.class);
Call<BaseResponse> call = sampleRequest.getCall();
// 异步发送请求
call.enqueue(new Callback<BaseResponse>() {
@Override
public void onResponse(Call call, Response response) {
response.body();
}
@Override
public void onFailure(Call call, Throwable t) {
}
});
// 同步发送请求
Response<BaseResponse> response = call.execute();
response.body();
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
3.2.2 Retrofit动态代理实现
接下来分析Retrofit内部是如何使用动态代理模式的:
public final class Retrofit {
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(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, Object... args)
throws Throwable {
// ...
// 真正需要执行的代码
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
}
网友评论