我们平时会接触到不少开源项目, 很多人都期望能够通过阅读源码理解更多东西,把从中学到的东西用于平时的框架使用,设计和编码实现过程。
不过,浩瀚的代码量,应该关注什么? 作为一个屌丝程序员,分享一下屌丝经验:
- 首先,你应该有一定的使用经验。从使用中,去找相关特性是如何实现的。
- 最好阅读一下官方文档,了解使用的场景,高层设计、特性介绍。做到心中有数。
- 关于设计模式。提前学习一下还是有用的,学习源码的时候就不用揪着设计模式不放,会崩溃的。
- 同上,很多源码书会画很庞大的类图,时序图等。这些看上去很高大上,然并卯。
- 还是要带的问题去跟踪,一次跟踪一小部分,就是一次要有一个关注点,集中分析。别走马观花。
- 建议使用maven等高大上工具关联源码,应该多调试调试,但是单步调试帮助不大。
- 同上,应该提高代码”猜想”能力,大步调试过去,验证自己的猜测。
- linus说: 烂程序员关心的是代码。好程序员关心的是数据结构和它们之间的关系。
- 多补充理论知识。虽然很花时间。
- 凑数的,找个感兴趣的开始吧。
上面废话很多,下面来个事例。
commons httpclinet 3.x 这是一个很超好用的库,实际上也是比较容易理解的。
我阅读的时候,列了一下自己的关注点或者问题列表。
- 如何打开HttpClient库的详细日志
- httpclient默认参数有哪些?如User Agent、Charset怎么进行定制?
- httpclient的连接是怎样管理的? 内部是连接池还是什么? HttpClient能用于多线程环境么?如何应用?
- 关于MultiThreadedHttpConnectionManager的数据结构是怎样的?
- uri和content中的字符编码是怎么处理的? 例如像处理带中文的路径。
- HttpClient#executeMethod实现细节,为什么hostconfig要克隆一份?为什么不能直接设置?
1 2 3 4 5 6 7 |
|
- HttpClient、HttpMethod(GetMethod、PostMethod)、HostConfiguration、HttpConnectionManager、HttpClientParams、HttpConnection、HttpState、AuthChallengeProcessor主要负责什么?
- 命令行参数、HttpClient、HttpMethod、HostConfiguration都可以设置params,有区别? 参数在框架中是怎样存储的?
1 2 3 4 5 6 |
|
- HttpClient会自动处理请求跳转? 会不会出现死循环? 怎样的响应才会自动跳转? 如何关闭这个特性
- HttpClient的自动重试功能是怎样? 怎么进行定制?
- HttpClient是使用java自带的HttpUrlConnection实现的么? 报文是怎么组装和解析的?
- 连接超时、读取超时、读写缓冲区、还有禁用Nagle等常见属性如何设置?
- 多次调用之间的cookie怎么管理的?
- chunked模式是怎么实现的? 多大刷一次?
大家可以参考这个,在阅读的时候,列出问题列表,然后从源码中找找答案。
细节是魔鬼:)
========================华丽的分割线========================
关于第8点,以MultiThreadedHttpConnectionManager为例,如何分析数据结构? (昨晚分析的,时间有限,不保证正确性)
从本质来说,整个链接管理的结构是:
1 2 3 4 5 6 7 8 9 |
|
代码就是围绕这些核心数据结构进行操作的。通过上面的基本结构,就可以实现以下特性:
- 总连接数和每主机总连接数限制。连接数默认50,每host默认2连接(经常容易忽略,通常需要定制)
- 能够防止连接丢失。如上面所说,拿出去的HttpConnection是加强过的,会关联到一个静态的ReferenceQueue,并使用一个线程ReferenceQueueThread不停监听并回收。
- 实现了获取连接的超时限制。就是通过waitingThreads实现的。当找不到空闲连接的时候就添加进去,然后wait。如果有releaseConnection的时候,就会interupt等待的第一个线程。我个人认为线程有可能被interupt之后仍然占用不到连接,从而排到最后去,真是悲剧。
- 能够支持连接闲时关闭。这个默认是需要主动触发,通过IdleConnectionHandler比较时间来实现的。
最后,这个类是支持多线程的,主要是使用了同步机制,锁定ConnectionPool对象实现的。
另外,HttpConnection对象实际上并不是一个正式的连接,要open之后才会真的建立连接。
实际上也是一个lazy代理对象,可以避免整个连接管理操作不被阻塞,只有到实际操作时open的时候才连接。
========================华丽的分割线========================
关于第9点,以commons-httpclient为例,这当中涉及到哪些理论基础呢? 简单列举一下:
- java弱引用、克隆特性
- 线程协调、中断机制
- 网络编码、http协议
- tcp相关参数的含义
- 常见对象池化技术