阅读源码最好的方法
画图(建立上帝视角)
类的跨度比较少的(JUC)画流程图
类的跨度比较大的(大型框架 spirng、netty、dubbo、zk等)画时序图
总结
思维导图
心态
慢慢读,静下心来,像读一本书一样去理解。
作用 | 快捷键 |
---|---|
返回至上次浏览的位置 | Ctrl+Alt+left/right |
切换代码视图 | Alt+left/right |
查看所有方法、属性 | ctrl+F12、alt+7 (mac:command+f12、command+7) |
查看方法调用关系 | alt+f7 ( 方法右键 -> find useges) 或者 ctrl + alt + h(全部出来了) |
查看类继承关系 | ctrl+h |
打开收藏夹 | alt+F2 |
返回上一调用层(不知道怎么一步步走到这里的) | 在debug模式下 step out,比如当前重写了框架提供的某个方法,想知道从哪里一步步过来的。 |
书签(Bookmarks)相关(不建议)
作用 | 快捷键 |
---|---|
打标签 | Ctrl Shift 数字添加标签,再次点击取消 ,或者鼠标点击到某一行,ctrl+F11添加书签(到某一行的行号位置右键set bookmark添加普通的,set bookmark with mnemonic是添加有数字的) |
跳转到第n个标签 | Ctrl + 数字 |
书签管理窗口 | Shift + F11(导航栏Navigate->bookMarks->show bookmarks),或者在左侧的Favorite(收藏夹)也能够查看 |
改变书签顺序 | 改变书签顺序 alt+↑、alt+↓(不论是有数字的还是普通的书签都可以排序,排序功能我用的2019.3.3不行,2019.3.2可以) |
单击以添加/编辑所选书签的描述。 | Ctrl+Enter |
单击以删除选定的书签。 | Alt+Delete |
如何同步?
通过搜索引擎没有找到好的办法,但是我在C:\Users\Administrator.IntelliJIdea2019.3\config\workspace\1Xk7dsjvaLv3yKonGopOrZMVL3v.xml里面找到了相关的配置,可以保存这个xml,甚至想办法,按照某种规则,替换掉另一台电脑的当前配置,直接导入。
mac是在cd ~/Library/Preferences/IntelliJIdea2019.3/workspace
纠正下:目前我没有发现能够同步书签的方法,只能保存上面xml,再次手动设置,如果谁有好的方法,请不吝告诉我,万分感谢!
具体查看我的另一篇文章:idea中书签的同步?
更新:通过书签的方式阅读源码不是一个很好的方式,不够直观。
委派模式
如果点击A方法的实现点击过去是一个接口,这个时候直接回来A方法然后点击被谁实现(option+command+b)
即如果遇到委派模式,想要看方法的实现,不要用command+b,用option+command+b
模板方法
如果点击一个方法欲找到真正的实现类,明确知道是A,却发现没有A中没有这个方法的实现,说明是在抽象类中进行的实现,在抽象类的模板方法中又回调会A
比如根据Dubbo中的SPI机制,明知道消费端的invoke是被(InvokeerInvocationHandler(MockClusterWrapper(FailOverCluster(directory)))).invoke() 层层包装,到了MockClusterWrapper中的this.invoker.invoke(invocation);却发现没有FailOverCluster,这个时候应该去看抽象类
继承
多平平无奇的两个字,可是平常就是一时想不到。
就是子类中没有看到需要的方法的时候,要想到去父类,父类会再调用相应方法回到子类本身,跟模板方法有点类似,但是不是抽象的。
Spring中命名含义
一个很好的阅读源码的技巧就是看他的命名,通过命名看出内在的含义。
如果方法是support结尾的、包名是support的,一般是工具类的意思,是扩展
如果方法是do开头的,说明真正要开始干活了
beans包中,都是配置、规范、标准
context是具体的实现
config包是保存配置信息
阅读顺序
if(){
...
}else if{
...
}else if{
...
}else if{
...
}else if{
...
}else{
...
}
这种格式的代码,直接看最后一个else,这里可能就是所有可能中第一次进来的地方,比如CHM、FutureTasl
核心方法
看核心方法,源码最后一行可能很关键,能把整个方法串起来,记最底部的方法和方法中的参数,一块的逻辑基本就明白了
例如:zookeeper中的watcher源码只要看到ReplyHeader r = cnxn.subllllmitRequest(h, request, response, wcb);就可以了,前面一大段只是对于各个参数的获取和封装。
关心主线
先关心主线,主线完成再看细节,否则容易陷入到细节中,思路混乱,所以有的方法只要知道目的就好了。
比如dubbo的服务发布、注册,以及消费端订阅,其中可能有服务降级、服务容错等策略,可以先跳过,避免影响整体思路
知其然知其所以然
想要明白dubbo中的调用机制,必须要懂dubbo中的spi机制,否则好几十个类,不知道究竟这个方法是在哪里被调用的,也根本无法继续往下看。