什么是代理设计模式 为某个对象提供一个代理,控制对这个对象的访问。对象和代理对象实现共同的父类或接口。
简单代理 比如去银行办卡,可以用机器办理,也可以找柜台。实现共同的父类和接口,对象能做的事情,代理对象也都可以做。
统一的接口
public interface IBank {
void bank();
}
办理业务的人
public class Man implements IBank {
@Override
public void bank() {
System.out.println("---- real");
}
}
业务员
public class Salesman implements IBank {
IBank realBank;
public Salesman(IBank iBank) {
this.realBank = iBank;
}
@Override
public void bank() {
System.out.println("---办理手续");
realBank.bank();
System.out.println("---结束操作");
}
}
public class Main {
public static void main(String[] args) {
Man realBank = new Man();
Salesman salesman = new Salesman(realBank);
salesman.bank();
}
}
动态代理
public class Main {
public static void main(String[] args) {
IBank realBank = new RealBank();
IBank iBank = (IBank) Proxy.newProxyInstance(IBank.class.getClassLoader(), new Class[]{IBank.class},
new BankInvocationHandler(realBank));
iBank.bank();
}
private static class BankInvocationHandler implements InvocationHandler {
IBank realBank;
public BankInvocationHandler(IBank realBank) {
this.realBank = realBank;
}
// proxy 为代理对象
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("--- bank");
Object object = method.invoke(realBank, args);
return object;
}
}
}
动态代理拦截view的点击事件
Hook源码中的简单应用。 比如拦截view的点击事件,做些额外的事情。
1,查看setOnClickListener方法源码,查看赋值的属性。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.textView);
TextOnClickListener textOnClickListener = new TextOnClickListener();
textView.setOnClickListener(textOnClickListener);
new HookViewClick().hook(textView);
}
private class TextOnClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Hello", Toast.LENGTH_SHORT).show();
}
}
}
在View的 ListenerInfo mListenerInfo;对象的mOnClickListener对象是实际持有者。
public void setOnClickListener(@Nullable OnClickListener l) {
if (!isClickable()) {
setClickable(true);
}
getListenerInfo().mOnClickListener = l;
}
ListenerInfo getListenerInfo() {
if (mListenerInfo != null) {
return mListenerInfo;
}
mListenerInfo = new ListenerInfo();
return mListenerInfo;
}
通过反射来获取到该对象。并且为该对象创建一个代理对象。通过反射将代理对象重新设置给mOnClickListener。
public void hook(View view) {
try {
// 通过反射获取到对象实例
Field mListenerInfoField = View.class.getDeclaredField("mListenerInfo");
mListenerInfoField.setAccessible(true);
Object o = mListenerInfoField.get(view);
// Method method = View.class.getDeclaredMethod("getListenerInfo");
// method.setAccessible(true);
// Object o = method.invoke(textView);
Class cl = Class.forName("android.view.View$ListenerInfo");
Field listenerInfoOnClickField = cl.getDeclaredField("mOnClickListener");
listenerInfoOnClickField.setAccessible(true);
View.OnClickListener yListener = (View.OnClickListener) listenerInfoOnClickField.get(o);
// 动态代理。
View.OnClickListener proxyOnClick = (View.OnClickListener)
Proxy.newProxyInstance(View.class.getClassLoader(),
new Class[]{View.OnClickListener.class},
new TextOnClickInvocationHandler(yListener));
// 静态代理
// TextOnClickProxyListener proxyOnClick = new TextOnClickProxyListener(yListener);
listenerInfoOnClickField.set(o, proxyOnClick);
} catch (Exception e) {
e.printStackTrace();
}
}
// 动态代理
private class TextOnClickInvocationHandler implements InvocationHandler {
View.OnClickListener textOnClickListener;
public TextOnClickInvocationHandler(View.OnClickListener textOnClickListener) {
this.textOnClickListener = textOnClickListener;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("----- invoke");
Object object = method.invoke(this.textOnClickListener, args);
return object;
}
}
//静态代理
private class TextOnClickProxyListener implements View.OnClickListener {
View.OnClickListener mOnClickListener;
public TextOnClickProxyListener(View.OnClickListener onClickListener) {
mOnClickListener = onClickListener;
}
@Override
public void onClick(View v) {
System.out.println("---- onclick Proxy");
mOnClickListener.onClick(v);
}
}
Retrofit中的动态代理
Retrofit retrofit = new Retrofit.Builder().baseUrl(baseUrl)
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.from(EXECUTOR)))
.addConverterFactory(GsonConverterFactory.create(gson))
.client(builder.build())
.build();
retrofit.create(clazz);
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service); //检查service是不是一个接口
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
@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);
}
// 对method的注解进行解析,构造成我们适配的对象,call或者observable
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}
Proxy 原理
一般是通过 Proxy.newProxyInstance(,,) 创建和使用代理对象。那么这个方法是怎么来创建出的代理对象呢?是怎么回调到InvocationHandler的invoke方法中的呢?
@CallerSensitive
public static Object newProxyInstance(
ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
throws IllegalArgumentException
{
final Class<?>[] intfs = interfaces.clone();
Class<?> cl = getProxyClass0(loader, intfs);
final Constructor<?> cons = cl.getConstructor(constructorParams);
return cons.newInstance(new Object[]{h});
}
在这个方法里发现,先是clone了一下接口,然后就调用了 getProxyClass0 方法来获取了一个Class。 然后通过 getProxyClass0 返回的代理类Calss,创建了一个对象。
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
return proxyClassCache.get(loader, interfaces);
}
而在 getProxyClass0 调用了 WeakCache 的get方法。WeakCache从名字来判断也可得知是一个用来缓存对象的。WeakCache原理, 而它的构造方法中第二个参数是创建一个 ProxyClassFactory 对象。
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";
// next number to use for generation of unique proxy class names
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
*/
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(intf + " is not visible from class loader");
}
// 不是interface的时候,抛出异常
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException("repeated interface: " + interfaceClass.getName());
}
}
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
long num = nextUniqueNumber.getAndIncrement();
// 生成代理类名
String proxyName = proxyPkg + proxyClassNamePrefix + num;
//生成类的byte
byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags);
try {
return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
}
}
private static native Class<?> defineClass0(ClassLoader loader, String name, byte[] b, int off, int len);
在这个方法里遍历了每一个Class,并生成 $Proxy0 类名,然后调用 ProxyGenerator.generateProxyClass来生成类的byte。defineClass0 是一个native方法,将byte内容写入到磁盘。
public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
final byte[] var4 = var3.generateClassFile();
return var4;
}
private byte[] generateClassFile() {
this.addProxyMethod(hashCodeMethod, Object.class);
this.addProxyMethod(equalsMethod, Object.class);
this.addProxyMethod(toStringMethod, Object.class);
Class[] var1 = this.interfaces;
int var2 = var1.length;
int var3;
Class var4;
for(var3 = 0; var3 < var2; ++var3) {
var4 = var1[var3];
Method[] var5 = var4.getMethods();
int var6 = var5.length;
for(int var7 = 0; var7 < var6; ++var7) {
Method var8 = var5[var7];
this.addProxyMethod(var8, var4);
}
}
Iterator var11 = this.proxyMethods.values().iterator();
List var12;
while(var11.hasNext()) {
var12 = (List)var11.next();
checkReturnTypes(var12);
}
Iterator var15;
try {
this.methods.add(this.generateConstructor());
var11 = this.proxyMethods.values().iterator();
while(var11.hasNext()) {
var12 = (List)var11.next();
var15 = var12.iterator();
while(var15.hasNext()) {
ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next();
this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10));
this.methods.add(var16.generateMethod());
}
}
this.methods.add(this.generateStaticInitializer());
} catch (IOException var10) {
throw new InternalError("unexpected I/O Exception", var10);
}
if (this.methods.size() > 65535) {
throw new IllegalArgumentException("method limit exceeded");
} else if (this.fields.size() > 65535) {
throw new IllegalArgumentException("field limit exceeded");
} else {
this.cp.getClass(dotToSlash(this.className));
this.cp.getClass("java/lang/reflect/Proxy");
var1 = this.interfaces;
var2 = var1.length;
for(var3 = 0; var3 < var2; ++var3) {
var4 = var1[var3];
this.cp.getClass(dotToSlash(var4.getName()));
}
this.cp.setReadOnly();
ByteArrayOutputStream var13 = new ByteArrayOutputStream();
DataOutputStream var14 = new DataOutputStream(var13);
try {
var14.writeInt(-889275714);
var14.writeShort(0);
var14.writeShort(49);
this.cp.write(var14);
var14.writeShort(this.accessFlags);
var14.writeShort(this.cp.getClass(dotToSlash(this.className)));
var14.writeShort(this.cp.getClass("java/lang/reflect/Proxy"));
var14.writeShort(this.interfaces.length);
Class[] var17 = this.interfaces;
int var18 = var17.length;
for(int var19 = 0; var19 < var18; ++var19) {
Class var22 = var17[var19];
var14.writeShort(this.cp.getClass(dotToSlash(var22.getName())));
}
var14.writeShort(this.fields.size());
var15 = this.fields.iterator();
while(var15.hasNext()) {
ProxyGenerator.FieldInfo var20 = (ProxyGenerator.FieldInfo)var15.next();
var20.write(var14);
}
var14.writeShort(this.methods.size());
var15 = this.methods.iterator();
while(var15.hasNext()) {
ProxyGenerator.MethodInfo var21 = (ProxyGenerator.MethodInfo)var15.next();
var21.write(var14);
}
var14.writeShort(0);
return var13.toByteArray();
} catch (IOException var9) {
throw new InternalError("unexpected I/O Exception", var9);
}
}
}
在这个方法里生成了代理类的内容,这个类继承了Proxy,并且实现了InvocationHandler。
在实现的接口中调用了 InvocationHandler 的 invoke 方法。第一个参数是代理对象,第二个是调用的方法,第三个是参数。