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,一经查实,立即删除!

相关文章

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 构成,现在要你分解成一…

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

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

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

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

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 方式…

hive基本操作与应用

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

Apache log4j是领先的日志记录框架

根据 从零周转开始的调查中, Apache log4j是领先的Java日志记录框架。 这实际上是一个非常有趣的调查。 它显示SLF4J最常用作伐木外墙,占61%。 但是,它似乎最常与Apache Log4j一起使用,52%的调查参与者都…

Centos6.8通过yum安装mysql5.7

Centos6.8通过yum安装mysql5.7 2017年07月13日 14:19:10 阅读数:1067 1.安装mysql的yum源 a.下载配置mysql的yum源的rpm包 根据上面3张图片中的操作下载下来的rpm文件可以通过如下命令获取: wget https://dev.mysql.com/get/mysql57-community-release-e…

Mvc+Hui+SqlSugar+Autofac+NLog+T4 架构设计(一)

一、前言 作为小菜鸟第一次写博客的我还有点小激动,最近开始打算着手写一个属于自己架构。算下来差不多最近花一周多的下班时间了来写这个框架,本来想整体架构开发完成测试完成后才写博客,怕自己没时间或失去动力,就先把自己架构设…

房价在手,天下我有 --反手就撸一个爬虫(终)

接上篇,科科,好,我们继续 我们在这里先把json数据入库吧~ 首先,database/scheme里定义好数据类型。 const mongoose require(mongoose)const detailHouseSchema new mongoose.Schema({ //定义数据模式link:String…

Spring MVC:带有CNVR卷的REST应用程序。 1个

不久前,我阅读了Paul Chapman撰写的有关内容协商视图解析器 (CNVR)的文章。 Spring Framework Blog上的那篇文章启发了我研究这个框架的领域。 因此,我开发了一个基于Spring MVC和CNVR的 REST示例应用程序。 该应用程序演示了REST…

《精通Spring 4.x 企业应用开发实战》学习笔记

第四章 IoC容器 4.1 IoC概述 IoC(Inverse of Control 控制反转),控制是指接口实现类的选择控制权,反转是指这种选择控制权从调用类转移到外部第三方类或容器的手中。 也就是由Spring容器借由Bean配置来进行控制。 DI(D…

微前端——无界wujie

B站课程视频 课程视频 课程课件笔记: 1.微前端 2.无界 现有的微前端框架:iframe、qiankun、Micro-app(京东)、EMP(百度)、无届 前置 初始化 新建一个文件夹 1.通过npm i typescript -g安装ts 2.然后可…

java executor spring_Spring+TaskExecutor实例

一 TaskExecutor接口Spring的TaskExecutor接口等同于Java.util.concurrent.Executor接口。 实际上,它存在的主要原因是为了在使用线程池的时候,将对Java 5的依赖抽象出来。 这个接口只有一个方法execute(Runnable task),它根据线程池的语义和…

小程序居然可以用WXS模拟实现过滤器!

小程序目前官方还没有出过滤器,特别不方便,但是可以用wxs来模拟过滤器,话不多说,直接上代码。当然,不熟悉wxs的可以先看一下 官方文档 1.新建一个filter.wxs的文件我个人建议是一个过滤器写一个wxs,避免引用…

ADF:使用HTTP POST方法进行URL任务流调用

众所周知,可以通过某些URL直接从浏览器或某些外部应用程序调用有限任务流。 如果任务流的属性“ URL invoke”设置为“ url-invoke-allowed”,则启用此功能,该功能通常在集成项目中使用。 通常,客户端(或调用者&#x…

java 项目做多级缓存_【开源项目系列】如何基于 Spring Cache 实现多级缓存(同时整合本地缓存 Ehcache 和分布式缓存 Redis)...

一、缓存当系统的并发量上来了,如果我们频繁地去访问数据库,那么会使数据库的压力不断增大,在高峰时甚至可以出现数据库崩溃的现象。所以一般我们会使用缓存来解决这个数据库并发访问问题,用户访问进来,会先从缓存里查…

Spring MVC:带有CNVR卷的REST应用程序。 3

这是带有CNVR的Spring MVC REST教程的最后一部分。 在这里,我将演示所有这些东西如何工作,这是我在前两部分中开发的。 对于每种类型的CRUD操作,这将分为四个部分:CREATE,READ,UPDATE,DELETE。 …

java 中io的删除文件_总结删除文件或文件夹的7种方法-JAVA IO基础总结第4篇

本文是Java IO总结系列篇的第4篇,前篇的访问地址如下:如果您阅读完成,觉得此文对您有帮助,请给我点个赞,您的支持是我不竭的创作动力。为了方便大家理解,我特意制作了本文对应的视频:总结删除文…

实现小程序canvas拖拽功能

组件地址 https://github.com/jasondu/wx-comp-canvas-drag 实现效果 如何实现 使用canvas使用movable-view标签 由于movable-view无法实现旋转,所以选择使用canvas 需要解决的问题 如何将多个元素渲染到canvas上如何知道手指在元素上、如果多个元素重叠如何知…