最近在阅读 Retrofit 的源代码,顺便整理一下 Java 反射类 Proxy 实现的动态代理。
在阅读 Retrofit 源代码之前,我一直以为 Retrofit 采用的是 注解 加 注解处理器(Annotation Processor)的方式来实现的网络请求的封装的,而事实上并不是这样的。Retrofit 的注解都是运行时注解(@Retention(RUNTIME)),而不是源代码注解(@Retention(RetentionPolicy.SOURCE)),这样就意味着,网络请求是在运行时通过反射的方式来组装的。
在组装网络请求时,用到了 Java 反射库中的 Proxy 来实现了动态代理。代码如下:
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();
private final Object[] emptyArgs = new Object[0];
@Override
public @Nullable Object invoke(Object proxy, Method method,
@Nullable Object[] args) throws Throwable {
// If the method is a method from Object then defer to normal invocation.
// 特殊的,比如 equals 方法,Object 自身的方法
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
// 平台的方法,
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// service 的方法,这里应该就是咱们接口定义的方法
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
Retrofit.create() 方法的入参是 Class<T> ,返回类型是 T ,这里的 T 是泛型。我们只写了个接口,并没有具体的实现类,而 create 方法却可以返回一个实现类,这里就是动态代理。
Proxy.newProxyInstance(ClassLoader ,Class<?>[] , InvocationHandler ) 方法入参为一个 ClassLoader ,一个 Class 数组,一个 InvocationHandler ,返回类型是 Object 。也就是通过这个方法,它会返回一个集成了给定接口的类的对象。
这个方法有三行核心的代码,第一行通过获取一个继承了所有接口的类;第二行获得该类的某个指定构造器;第三行通过构造器实例化对象。
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {
if (h == null) {
throw new NullPointerException();
}
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, interfaces); // 1 获得类
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
// constructorParams 的定义:
// private final static Class[] constructorParams =
// { InvocationHandler.class };
final Constructor<?> cons = cl.getConstructor(constructorParams); // 2 获得构造器
return newInstance(cons, h); // 3 实例化对象
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
}
}
通过 Proxy.getProxyClass0(ClassLoader , Class<?> ) 方法,返回一个集成了所有接口(interface)的类(class)对象。方法体里, proxyClass 是最终被返回的类对象。这个方法比较长,但是咱们可以分几个大的步骤。
下面是 getProxyClass0() 方法,我做了一些删减。
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// 最终要返回的对象,代理类
Class<?> proxyClass = null;
/* collect interface names to use as key for proxy class cache */
String[] interfaceNames = new String[interfaces.length];
// for detecting duplicates
Set<Class<?>> interfaceSet = new HashSet<>();
// 1. 各种校验
for (int i = 0; i < interfaces.length; i++) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
*/
String interfaceName = interfaces[i].getName();
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(interfaceName, false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != interfaces[i]) {
throw new IllegalArgumentException(
interfaces[i] + " is not visible from class loader");
}
/*
* Verify that the Class object actually represents an
* interface.
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
*/
if (interfaceSet.contains(interfaceClass)) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
interfaceSet.add(interfaceClass);
interfaceNames[i] = interfaceName;
}
// 2. 从 loaderToCache 里,获得 proxyClass ,这里代码有省略
List<String> key = Arrays.asList(interfaceNames);
Map<List<String>, Object> cache;
synchronized (loaderToCache) {
cache = loaderToCache.get(loader);
}
synchronized (cache) {
do {
Object value = cache.get(key);
if (value instanceof Reference) {
proxyClass = (Class<?>) ((Reference) value).get();
}
if (proxyClass != null) {
return proxyClass;
}
} while (true);
}
// 3. 创建代理类
try {
// 定义代理类的包
String proxyPkg = null; // package to define proxy class in
for (int i = 0; i < interfaces.length; i++) {
int flags = interfaces[i].getModifiers();
if (!Modifier.isPublic(flags)) {
// 这里省略了代码
// 如果接口定义不是 public 的,那么接口需要在同一个包下
}
}
if (proxyPkg == null) {
// if no non-public proxy interfaces, use the default package.
// 如果没有非 public 的接口,那么使用默认的包
proxyPkg = "";
}
{
// Android-changed: Generate the proxy directly instead of calling
// through to ProxyGenerator.
// 获得接口定义的所有方法。这里 Android 和 Java 有一些不一样。
List<Method> methods = getMethods(interfaces);
Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
validateReturnTypes(methods);
List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods);
Method[] methodsArray = methods.toArray(new Method[methods.size()]);
Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]);
/*
* Choose a name for the proxy class to generate.
*/
final long num;
synchronized (nextUniqueNumberLock) {
num = nextUniqueNumber++;
}
String proxyName = proxyPkg + proxyClassNamePrefix + num;
// 生成代理类
proxyClass = generateProxy(proxyName, interfaces, loader, methodsArray,
exceptionsArray);
}
// add to set of all generated proxy classes, for isProxyClass
proxyClasses.put(proxyClass, null);
} finally {
// 省略代码
}
return proxyClass;
}
generateProxy 是一个 native 方法。
private static native Class<?> generateProxy(String name, Class<?>[] interfaces,
ClassLoader loader, Method[] methods,
Class<?>[][] exceptions);
Proxy.getMethods(Class<?>[])用来获得代理类应该集成的所有方法。因为接口可能存在继承,所以这里需要用到递归。
private static List<Method> getMethods(Class<?>[] interfaces) {
List<Method> result = new ArrayList<Method>();
try {
result.add(Object.class.getMethod("equals", Object.class));
result.add(Object.class.getMethod("hashCode", EmptyArray.CLASS));
result.add(Object.class.getMethod("toString", EmptyArray.CLASS));
} catch (NoSuchMethodException e) {
throw new AssertionError();
}
getMethodsRecursive(interfaces, result);
return result;
}
private static void getMethodsRecursive(Class<?>[] interfaces, List<Method> methods) {
for (Class<?> i : interfaces) {
getMethodsRecursive(i.getInterfaces(), methods);
Collections.addAll(methods, i.getDeclaredMethods());
}
}
实例化代理类的一个关键是,每个代理类都有一个特殊的构造器,也就是每个代理类都有一个 InvocationHandler 对象,在调用代理类的方法的时候,实际调用的是 InvocationHandler 的方法。这样,我们只需要实现 InvocationHandler 就可以实现动态代理了。
Each proxy class has one public constructor that takes one argument, an implementation of the interface {@link InvocationHandler}, to set the invocation handler for a proxy instance. Rather than having to use the reflection API to access the public constructor, a proxy instance can be also be created by calling the {@link Proxy#newProxyInstance Proxy.newProxyInstance} method, which combines the actions of calling {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the constructor with an invocation handler.
private static Object newInstance(Constructor<?> cons, InvocationHandler h) {
try {
return cons.newInstance(new Object[] {h} );
} catch (IllegalAccessException | InstantiationException e) {
throw new InternalError(e.toString());
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString());
}
}
}
整个代码整理下来,我们大概知道,动态代理主要有两个核心的类,一个是 Proxy 类,一个是 InvocationHandler 类。通过 Proxy 类,我们可以获得一个接口的代理对象,调用代理对象的方法时,会转交给 InvocationHandler 来处理,于是,我们只需要实现 InvocationHandler 来实现具体的业务逻辑。
这样就可以把方法的定义和方法的实现分离。
- EOF -
本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处,尊重他人劳动。
转载请注明:文章转载自 Binkery 技术博客 [https://binkery.com]
本文标题: Java 动态代理 Proxy
本文地址: https://binkery.com/archives/612.html