最近学习asm框架顺便复习了下动态代理的相关知识,这里简单做一下记录。
java中动态代理注意通过proxy的newProxyInstance方法实现。
'''
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h){
//这里的实现就不细究了,有兴趣可以自己阅读源码
}
'''
入参为一个classloder对象,通常可以传入目标class的classloder,第二个参数通常为需要被代理实现的interface或者class方法。第三个则是代理实现类,用于处理动态代理生成的实现类的具体实现。
这里看一下InvocationHandler接口,只有一个invoke方法。当被动态代理的实现类的里面会返回当前被代理的对象,以及该对象
'''
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
'''
这边拿retrofit的create方法来具体分析一下
'''
public <T> T create(final Class<T> service) {
//判断service是否合法,动态代理理论上可以代理class或者interface,但是retrofit里要求必须是interface
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, @Nullable Object[] args)
throws Throwable {
//这里是InvocationHandler的实现,每当该代理实例的某个方法被调用的时候就会触发invoke方法,并在对应的参数里返回对应的方法。
// If the method is a method from Object then defer to normal invocation.
//这边是object的方法直接调用不干预
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//这里是去根据不同的方法执行对应的逻辑,具体的内容就不分析了,这边主要是单独去记录动态代理的。后续如果retrofit的实现忘记的差不多了那再去写一篇retrofit的分析好了。
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
'''
总体而言动态代理在使用上有点像asm的简化版,前者是预先通过InvocationHandler的invoke方法来拦截并处理被代理对象的方法执行,而后者则是在编译期,拦截所有特定类包括方法执行,参数创建,内存分配在内的所有生命周期并对其做相应的字节码修改最后输出。
网友评论