hprose for java 教程_hprose for java源码分析-4

4.1 疑窦丛生

书接上回。上回说到,

从HproseClient.java ------------------------- (#0)

f85852f7ea4893ae1d3ae5589f30ad6c.png

invokeHandler.handle()开始,将经历一个漫长的调用过程,下面把整个调用链粘出来,先认识下这个庞然大物。

( >>> 表示调用到, 后面 xxx.java,表示源代码所在文件,接下来的是函数源码 )

>>> HandlerManager.java ----------------------- ( #1 )

65319c4142ae106b5a6668047e404063.png

>>> HproseClient.java ------------------------------(#2 )

f81e785a169b99f477a258e2a3185341.png

>>> HproseClient.java ------------------------------ (#3 )

4a1062341c5f7992b72e0a7302301826.png

534行的调用的encode()方法未贴出源码,之后会介绍。

>>> HandlerManager.java ----------------------- (#4 )

c9f74677a29b8b8b5d3974a0bb93b33c.png

>>> HproseClient.java ----------------------------- (#5 )

8c4219887d97280cad67dccb09216943.png

>>> HproseClient.java ------------------------------(#6)

5ab6ff5f67c72667529cd9bb747c2d33.png

>>> HandlerManager.java -------------------------(#7 )

b4b420b2cb8ab7237b49e7c2b7c16b2c.png

b4b420b2cb8ab7237b49e7c2b7c16b2c.png

>>> HproseClient.java -------------------------------(#8 )

c1f3a966386e282cc4c27ebea0d3f3fd.png

>>> HproseClient.java ----------------------------- (#9 )

20d8f38ccddaaadbeb9f336476d89790.png

>>> HproseTcpClient.java ------------------ (#10)

add51f1240db26e28f3d93c2b58daa64.png

>>> HproseTcpClient.java ---------------- (#11)

d9efba513c1e32929b32a0f0f459f720.png

到#11暂告一段落,让我喘口气先。这段调用步骤太多了,耐心看到这里的各位看客,都是好样的,为你点赞。继续,加油。

能不能简化一下呢?好像不能,这段调用一气呵成,没有可以跳过的步骤。然调用步骤虽多,每个函数源码行数并不多。看来,还得耐心分析一下。

初看这段调用,会被几件事情搞晕:

1). #0中的invokeHandler.handle(name, args, context) 与 #1中的 invokeHandler(name, args, context)。

这2处都出现了 invokeHandler,从#0看 invokeHandler是实例对象,从#1看,invokeHandler又是函数。

invokeHandler到底是函数还是实例对象。

2). #2,#3又出现2处invokeHandler同名函数,这比较容易理解,这2个是重载函数,因为第3个参数类型不一样。

3). #3中的 beforeFilterHandler.handle(stream.buffer, context) 与 #4中的 beforeFilterHandler(request, context) 2处同名的 beforeFilterHandler, 晕乎乎分不清,它到底是函数还是实例对象。

还有后面 的 afterFilterHandler.handle(request, context) 与 afterFilterHandler(request, context)。

4). beforeFilterHandler,与afterFilterHandler,作用是什么?

5). #11中,首次调用142行fetch() 函数时,返回的conn为null,于是send不会调用。这个调用链就会一步一步的返回到最初 #0处。而此时,数据还没有发向网络,RPC调用结果并未从服务器端返回。也就是说,在并未收到服务器端调用结果的情况下,#11处的调用链开始逐层返回了,而这种返回可能会直接返回到链的调用最初始处,即 obj.hello("world"),这个结果是啥呢?第一回说过,在服务器端未返回结果前,客户端会处于等待状态,直到有数据了,客户端才会返回到最初调用处。客户端是如何等待的,又是在哪一步等待的?

6). 最让人头疼的是 #7中afterFilterHandler(request, context)调用完后,后面接了一个.then调用,即

afterFilterHandler(request, context).then(new Func()

同样beforeFilterHandler也有类似情况。

再沿调用链仔细看一下,几乎每处都出现了 .then() 的情况,这究竟是何方神圣?

疑问很多,不过值得期待的是,这段调用是整个客户端的核心部分,这部分弄通了,就掌握了客户端关键,而其它部分是张飞吃豆芽,小菜一碟。

4.2 抽丝剥茧

接下来一个个分析上面的疑问。

1. invokeHandler同名问题。

事实上,在一个java类里面,成员变量与方法可以同名。如下面这个类

223cf0ea14492f29b5adf7157b577385.png

map方法与map成员变量虽是同名的,但java允许这样做。

不过同名也给我们带来了困扰,看来,为了使代码看起来更清晰些,需要人为避免一些同名出现。

beforeFilterHandler, afterFilterHandler也是这个问题。

因此4.1中的问题1), 3),一个为实例对象,一个为方法。

2. #2, #3处的重载。看#2处 invokeHandler,它覆盖了基类(HandlerManager)中的函数,基类中定义的第3个参数类型是HproseContext,但客户端用的是 ClientContext 类型,所以定义了一个 invokeHandler的

重载函数,来接收 ClientContext类型,即#3处的代码。

看到ClientContext,不禁要问,难道还有 ServiceContext?确实有,只不过ServiceContext在服务器端使用。同样,服务器端会遇到类似的重载问题。

由此看来,方法重载虽然好用,但用多了,也会造成困扰,还是慎用吧。当然如果只有几个重载方法,还是可以的,如果有几十个,或上百个,想分清楚谁是谁,也是有难度的。

3. beforeFilterHandler的作用。

#3中,beforeFilterHandler.handle()调用前,先调用了encode(name,args,context),把所调方法的名称,参数,写入了一个流stream中。beforeFilterHandler.handle()作用是,在hprose继续处理stream之前,准确的说是在调用

dece6dca75de20baae38b5d6e983c519.png

方法前( #6中341行 )

可以先给用户去做一些处理。默认情况下 beforeFilterHandler引用的是

HandlerManager.defaultBeforeFilterHandler 实例对象,可通过下面的方法来添加外部handle,见下面的代码:

HandlerManager.java

03c33546b6cde3f6bddb7c382955b221.png

调用addBeforeFilterHandler之后,beforeFilterHandler引用已经改变了,此时再调用

beforeFilterHandler.handle()时,首先调用的将是外部设置的那个handle了,于是在这个自定义的handle里,

可以对传入的ByteBuffer对象做额外处理。FilterHandler接口定义如下:

4bc4b9a4c7fbcf46eceaaddc894eeefc.png

4bc4b9a4c7fbcf46eceaaddc894eeefc.png

4. afterFilterHandler的作用。

同样的道理,对于afterFilterHandler.handle()是指在调用 outputFilter方法后( #6中341行 ),可以由外部做的事情,afterFilterHandler 默认情况下引用 HandlerManager .defaultAfterFilterHandler 实例,通过下面的方法

HandlerManager.java中

e4b3b4e5c55474853ce2847f6daa36b1.png

来改变 afterFilterHandler的引用。

解决了 4.1中几个疑问,还有2个有待解决,一是 .then 问题,另外一个客户端如何等待问题?

先解决 .then问题,再来看客户端等待问题。

请继续关注下集--何方神圣。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367032.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Git可视化极简易教程 — Git GUI使用方法

Git可视化极简易教程 — Git GUI使用方法 学习了:http://www.runoob.com/w3cnote/git-gui-window.html转载于:https://www.cnblogs.com/stono/p/9026292.html

如何用堆栈来保存和恢复滚动条位置

问题背景 在单页应用中,翻页一般通过display:none将先前的面板(一般就是个div容器)隐藏,然后将本次需要展现的面板设置成display:block(当然,还可能加点css切换动画,不过不影响我们本次的讨论结…

如何在Hibernate中维护表的历史记录

为了维护数据库的历史记录或跟踪数据库表行的修改,我们创建了一个版本表,其中包含与原始表相同的字段。每当原始表被更改时,我们都会在版本表中创建另一个条目。 因此,对于每个更新查询,我们都必须在版本表中编写一个插…

java批量提取文件夹名称_bat 批量提取指定目录下的文件名

bat 批量提取指定目录下的文件名下面是批量获取指定目录下的文件名的核心代码echo offecho text inputset inputset /p input:echo %input% is inputcd %input%rem echo onfor %%a in (*) do (echo %%a is input)cd ..如下是sql server执行对应脚本文件sqlcmd -Spcserver -dmas…

埃及分数The Rotation Game骑士精神——IDA*

IDA*:非常好用的搜索,可以解决很多深度浅,但是规模大的搜索问题。 估价函数设计思路:观察一步最多能向答案靠近多少。 埃及分数 题目大意: 给出一个分数,由分子a 和分母b 构成,现在要你分解成一…

[UE4]创建Shooter基类,2种方法

一、可以通过直接修改"BP_FPPCharacter"的名字为“BP_Shooter”作为基类,然后新建一个"BP_FPPCharacter"继承自“BP_Shooter”。 这种方法适用于各个类对"BP_FPPCharacter"依赖不多的情况。 二、创建一个“BP_Shooter”继承于“Chara…

美团扫码付的前端可用性保障实践

开篇 2017年,美团金融前端遇到了很多通用性问题,特别是在保障前端可用性的过程中,我们团队也踩了不少“坑”,在梳理完这些问题以后,我们还专门做了第31期线下沙龙给大家进行了分享。不管是在面试过程中与候选人讨论&a…

Servlet上传文件和下载文件示例

Java Web应用程序中的文件上载和下载以及常见任务。 由于最近我写了很多有关Java servlet的文章 ,因此我想提供一个使用servlet上传和下载文件的示例示例。 用例 我们的用例是提供一个简单HTML页面,客户端可以在其中选择要上传到服务器的本地文件。 在提…

用java单源最短路径问题_单源最短路径-贪心算法

单源最短路径,关于这个问题的贪心算有点不好理解,分析后续补充,代码也需要后续优化,便于理解package test;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/*** Created by sa…

APPLE STORE

直接在设置中,使用查看APPLE ID是无法更改的,现在必须要有所在区域的信用卡信息,支付方式无法像以前一样选择“无”。 查询后发现,有人说icloud3.0,即这个旧版的可以进行更改,于是下载。 但发现一个问题,输…

vue项目打包后文本溢出代码消失问题

补充 https://www.cnblogs.com/richard1015/p/8526988.html vue webpack 打包编译-webkit-box-orient: vertical 后消失 解决方案 optimize-css-assets-webpack-plugin这个插件的问题 注释掉webpack.prod.conf.js中下面的代码 new OptimizeCSSPlugin({cssProcessorOptions: c…

前端图片canvas,file,blob,DataURL等格式转换

最近用到一些图片相关的操作,记录一下笔记。 将file转化成base64 场景: 获取到一个file类型的图片,如果直接在html中预览?这里就是利用html5的新特性,将图片转换为Base64的形式显示出来。有两种方法: 方法…

java创建异步多线程_Java创建多线程异步执行实现代码解析

实现Runable接口通过实现Runable接口中的run()方法public class ThreadTest implements Runnable {public static void main(String[] args) {Thread thread new Thread(new ThreadTest());thread.start();}Overridepublic void run() {System.out.println("Runable 方式…

Java中的状态设计模式–示例教程

状态模式是行为设计模式之一 。 当对象根据其内部状态更改其行为时,将使用状态设计模式。 如果必须根据对象的状态更改其行为,则可以在对象中使用状态变量,并使用if-else条件块根据状态执行不同的操作。 状态模式用于通过上下文和状态实现提…

JS 循环遍历 总结

一、循环遍历语句 for...in... (ES5) 语法:javascript for(keys in obj){}适用:遍历对象说明:   1.keys表示obj对象的每一个键值对的键(键名),所有循环中,需要使用obj[keys]来取到每一个值。 …

java之平台无关

java虚拟机是执行字节码文件(.class)的虚拟机进程。 java源程序(.java)被编译器编译成------>字节码文件(.class),然后字节码文件,将由java虚拟机,解释成------>机器码&#x…

适用于ActiveMQ 5.9的Apache Camel Broker组件

将Apache Camel嵌入ActiveMQ代理可以为使用Camel的集成功能扩展消息代理提供极大的灵活性。 Apache Camel路由的另一个好处是,如果使用activemq组件 ,则可以避免远程连接到ActiveMQ的序列化和网络开销。 关于Apache ActiveMQ真正伟大的事情之一是&#x…

java rpg对战_RpgGame.java

import java.util.Scanner;public class RpgGame {public static void main(String[] args) {System.out.println("--------------------亲爱的勇士欢迎来到文字世界--------------------");System.out.println("--------------------这是一个充斥着危险的世界&…

hive基本操作与应用

通过hadoop上的hive完成WordCount 启动hadoop Hdfs上创建文件夹 上传文件至hdfs 启动Hive 创建原始文档表 导入文件内容到表docs并查看 用HQL进行词频统计,结果放在表word_count里 查看统计结果 转载于:https://www.cnblogs.com/cairuiqi/p/9048256.html

python - classs内置方法 solt

solt # __solt__ # 是一个类变量,变量值可以是列表、元组或者是可迭代对象,也可以是一个字符串 # (以为这所有实例只有一种数据属性) # # 作用:(为了节省内存空间,减少过多的实例属性所占用的内存空间) # 优点: # 1.使用_solt__以后,实例的__dict__属性被去除,从而达到节省…