远程代理
《Head First 设计模式》中讲,怎么毫无印象啊,再去看一遍,用 Java 内置的 RMI 举例,当年肯定是因为过于复杂难懂放弃了。现在看,第一反应是 Android 通过 AIDL 那一套的 Binder 机制,应该就是这个东西。
C/S 架构中,Client 不好直接调用 Server,Client 端有个辅助对象叫 Stub(桩),服务端有个辅助对象叫 Skeleton(骨架)。
书里大致流程应该是:
- Server 生成 Skeleton,Stub
- Server 向一个中间的桥梁 Registry 中注册绑定那个 Stub
- Client 从 Registry 找到对应 Stub
- Client 调用方法序列化后,通过 Stub 传到了 Skeleton,Skeleton 反序列化后调用 Server
- 返回结果再从 Skeleton 传给 Stub,进而到了 Client。
在 Android 里,创建 AIDL 文件,会自动生成一个类,这个类其实就是相当于服务端同时生成了 Stub 和 Skeleton。
内部生成子类 Stub,继承自 Binder,感觉它应该就是服务端的 Skeleton。
在 Stub.asInterface
方法中,当没有跨进程的时候,就是把这个 Stub 给客户端,相当于并不是什么远程调用,不需要做代理,但从架构来说,还是按需要远程调用的那一套来,这样保持统一;当需要跨进程时,返回 Stub 的代理 Proxy 给客户端,就相当于 Client 从 Registry 中查找到对应的 Stub。
代理类 Proxy 中定义了要调用的远程方法,就是将一些信息序列化通过 transact
方法传到服务端的 Stub 类,服务端在 onTransact
中接收到,反序列化,真正调用服务端的方法。返回值放到 _reply
,这是一个序列化的对象,然后 Proxy
再从 _reply
把结果取出来。
当客户端 bindService 时,找到了桥梁 Binder,然后调用它的 asInterface,相当于从 Registry 中找到对应的 Stub 代理。