动态代理定义
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)
throws IllegalArgumentException {
}
参数类型解释
newProxyInstance方法
返回值: Object是interface的实例
参数: ClassLoader类加载器,interfaces实现的接口数组,InvocationHandler接口对象
使用方式
通过Proxy类的newProxyInstance静态方法即可获取到接口对象,
通过对象的方法调用即可实现对动态代理类真正的方法调用。
举例
public interface Test{//接口类Test
List<String> test1(String str);
List<Integer> test2(int id);
}
Object object = Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[]{Test.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
});
Test test = (Test)object;
List<String> list = test.test1("ss");
1、定义接口类Test
2、通过Proxy.newProxyInstance方法获取对象Object
3、Object对象强转为Test对象test
4、test.test1("ss")方法调用实现对代理类的对应方法调用
5、上一步的test1方法调用之后,InvocationHandler接口的invoke方法被回调(此处可实现自己的逻辑)
设计
对生成的object对象打印object.getClass().getName() 输出结果:com.sun.proxy.$Proxy0
可见$Proxy0类便是动态代理机制为我们自动生成的类,该类继承Proxy,实现Test接口,所以object对象可以强转为Test对象
生成$Proxy0类的技术采用字节码操作技术(目前存在Javassist ASM Cglib 其中Cglib是对ASM的封装版)
以上,产生的$Proxy0类的存在对使用者隐藏,而是通过InvocationHandler接口把外部的Test接口与内部的$Proxy0联系起来。
再说如何联系:
使用JDK代码ProxyGenerator.generateProxyClass("aa", new Class[]{Test.class});
便获取到代理类$Proxy0的字节流,再保存到文件之后如下:
public final class aa extends Proxy implements Test{
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m4;
private static Method m0;
public final List test1(String paramString)
{
try
{
return (List)this.h.invoke(this, m3, new Object[] { paramString });
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
}
通过代码可知:举例中第4步test.test1("ss")的调用其实是调用了aa类的test1的方法,而this.h就是
newProxyInstance的第三个参数,所以举例中第4步的调用使得第5步InvocationHandler接口的invoke方法被回调
其中,ProxyGenerator类在Android Studio中不可见(需要自行下载rt.jar对应的类重新编译),可使用IDEA查看
关于字节码操作技术可参考 https://mp.csdn.net/mdeditor/87877612#