1. 为什么要读源码?
- 学习设计经验和思考模式
- 提升自己设计水平和思维方式
- 到实际项目中运用, 提升代码水平
2. 读源码的基础
- 熟悉面向对象的思维和设计(OOA && OOD)
- 设计模式: 可以通过《设计模式之禅》、《Java 设计模式及实践》、《Head first 设计模式》等来学习
- 一定的算法和数据结构基础
3. 方法论
A. 先会用再去读
- 要对源码的基本用法有了解, 先看看demo或说明文档
- 这样才能有一个整体的框架和目的, 这个是在做什么, 不然容易迷失
B. 循序渐进
- 可以先从简单源码项目: commons-lang、commons-collection、guava、mapstruct 等工具性质的源码.
- 或者看一些大型项目的简单版入手:,比如: spring 的简易版、 dubbo 简易版. 看透了再看原版就会更轻松.
C. 跑不起来不读
- 代码能运行起来, 才能debug, 设置断点.
- IDE在debug模式时会提醒你调用的具体是那个类, 不然遇到有太多实现类的接口时, 就会迷失方向 .
D. 先整体后局部, 避免陷入细节
- 要有整体思维, 先对框架有整体认识, 才能避免陷入局部细节. 对于一些大型的源码(几十万甚至上百万行代码)的, 读核心的原理,关键特性的实现,高抽象层的几个关键步骤即可。
- 很多细节是别人经过长时间多次迭代产生的, 要完全看懂太费劲. 而且意义不大, 脱离了环境就没有用了
- 几个整体:
- 架构: 很多文档会写出框架的架构, 先了解核心原理, 再看具体实现
- 项目结构: 可以看项目的目录结构, 再看具体
- 类: 先看继承关系和方法列表, 可以对类的本质和核心功能有一定认识, 以及发现一些意外的函数等收获
E. 抱有目的, 切勿走马观花
- 这个框架是为了解决什么问题?
- 和同类比有什么优缺点?为什么有这些优缺点?
- 注重逻辑和思想: 作者为什么先写A再写B? 为什么使用这种数据结构?探寻背后的原因
- 是否用到设计模式,为什么这么用 , 是如何实现的? 是否高内聚低耦合? 是不是体现某种优化思想?
F. 先猜想后验证
- 要设想如果自己是作者,该怎么设计框架、如何编写某个类(类应该有什么方法)、某个函数的代码(实现逻辑)。最后和源码进行对比,发现差异, 这样融入了自己的思考, 对作者的意图理解更到位, 印象也会更深刻. 也可以补全自己的知识漏洞.
- 先猜想后验证即是从设计者的角度观察源码, 这样可以避免"对着答案做题". 的误区, 真正意识自己的不足, 有自己的收获.
G. 抓住一条线索到底
- 多角度理解:
- 解决问题角度(debug)
- 设计者角度
- 性能优化
- 设计模式角度: 加深设计模式使用场景的理解, 如何使用设计模式.
- 看注释(尤其遇到一些特别的设计): 了解该函数的功能,每个参数的含义,异常发生的原因
- 单元测试: 通过单元测试来进行模块断点调试, 理清细节.
- 提交角度: 研究某个类是如何演进的, 看提交记录是很有效的. 可以学习到早期版本的问题, 是如何解决优化的.
- Issues角度: 了解源码的BUG或问题, 为什么会产生, 作者如何妥协使用什么解决方案等.
- 弄清楚原理,流程即可
- 可以使用SequenceDiagram来快速理清调用过程
H. 及时输出
- 输出过程整理你的思路, 确认你真正理解
4. IDEA小技巧
- 安装SequenceDiagram插件中, 选择方法名, 右键可以生成Sequence Diagram图(时序图), 可以了解方法的执行后的具体调用, 也可以点击跳转.
- 快捷键Ctrl/command + F12, 可以调出该类的方法列表, 点击跳转到对应方法.
- 快捷键Ctrl/command + Shift+I , 可以在小窗口显示某个参数或子函数的源码 ,避免跳转打乱节奏.