为什么要学习源码?源码这块面试会怎么问呢?如何阅读源码?
为什么要学习源码?
学 习优秀的代码实践
如果我们沉浸在自己的世界,整天 CRUD,实际是很难提高自己的编码能力,重复编码提升的不过是熟练度罢了!
如果我们想要写出质量更高、扩展性更好的代码,我们要做的事情非常简单:看一些技术大佬是怎么写的,模仿就完事了。
这个模仿不同于照葫芦画瓢,我们需要搞懂优秀设计背后的原理。
那怎么检验自己是否掌握了呢?很简单,看自己能不能在后续的编码中实践就好了。但是,切记不要为了用“好的编码实践”而用,一切要结合业务实际需要。
一些不错的开源项目,都是一些技术大佬们几个月甚至是几年的成果。只要肯花时间看,我们一定能从源码中学到很多东西。
我们需要重点关注源码中的这些点:
- 如何抽象接口的?
- 如何运用设计模式的?
- 如何实践 SOLID 软件设计原则的?
- 有哪些优秀的编码实践?
- ......
借鉴
如果我们想要设计一个类似的框架或者轮子的话,参考已有的优秀框架不失为一个好手段。俗话说的好:“他山之石可以攻玉”。
我们平时接触到的很多开源项目都是例子,比如阿里开源的消息队列 RocketMQ 就借鉴了 Kafka 。
面试需要
据我观察,大部分真正愿意去看源码的 朋友都是为了面试。这些朋友会找到对应框架比较重要的部分来学习源码,拿 Spring Boot 来说的话,就是 Spring Boot 启动流程、自动配置原理...。
确实,短时间内突击源码,我们一定要重点关注那些重要的地方。
但是,这种为了面试而突击源码的方式,往往很难真正学到源码的精髓,能收货的东西也会很有限。
项目需求
很多时候,我们阅读源码是因为项目需要。
比如说我们的项目在前期引入了某个开源框架,但是到项目中期的时候,我们发现这个开源框架并不能很好地满足我们的需求,甚至说还有一些小 bug 。与这个开源框架相关的负责人员交涉之后,我们的反馈并没有得到响应。这个时候, 我们就需要自己去实现某些功能以及修复某些 bug。想要做这些事情的前提是:我们当前对这个开源框架某一块的源码比较熟悉了。
源码面试这块会怎么问?
首先,你需要明确一点的是:随便一个框架的源码都 10w+行了,都看一遍是不可能的。你需要挑选比较重要的地方看。
拿 Spring/Spring Boot 源码举例:你一定要去看 IOC 和 AOP 具体的实现,要知道一个 Spring Bean 是如何一步一步被创建出来的。一定要搞清 Spring Boot 是如何实现自动配置的。
源码面试这个不会太细节。如果你知道的话一定是加分项,不知道的话不一定就会被 pass。不过你写简历的时候尽量写清楚点,写清楚自己看过哪部分的源码。
平时学习过程中,有时间的话可以多看看源码,对于提升自己的能力非常有帮助!
如果你不知道阅读什么源码的话,可以先从 JDK 的几个常用集合看起。另外,我比较推荐看 Dubbo 的,因为感觉会稍微相对容易一点,模块划分清晰,注释也比较详细。搞清楚了 Dubbo 基本的原理之后,看起来就没那么吃力了。
有哪些值得阅读的优秀源码?
下面有部分内容是摘自朋友写的一篇文章:《如何提升代码质量 - Thoughtworks 洞见》
JDK
为什么要看 JDK 源码?
- JDK 源码是其它所有源码的基础,看懂了 JDK 源码再看其它的源码会达到事半功倍的效果。
- JDK 源码中包含大量的数据结构知识,是学习数据结构很好的资料,比如,链表、队列、散列表、红黑树、跳表、桶、堆、双端队列等。
- JDK 源码中包含大量的设计模式,是学习设计模式很好的资料,比如,适配器模式、模板方法模式、装饰器模式、迭代器模式、代理模式、工厂模式、命令模式、状态模式等。
- JDK 源码中包含大量 Java 的高阶知识,比如弱引用、Unsafe、CAS、锁原理、伪共享等,不看源码是很难学会这些知识的。
JDK 源码阅读顺序 :
java.lang
包下的基本包装类(Integer、Long、Double、Float
等),还有字符串相关类(String、StringBuffer、StringBuilder
等)、常用类(Object、Exception、Thread、ThreadLocal
等)。java.lang.ref
包下的引用类(WeakReference、SoftReference
等)java.lang.annotation
包下的注解的相关类java.lang.reflect
包下的反射的相关类java.util
包下为一些工具类,主要由各种容器和集合类(Map、Set、List
等)java.util.concurrent
为并发包,主要是原子类、锁以及并发工具类- java.io 和
java.nio
可以结合着看 java.time
主要包含时间相关的类,可以学习下 Java 8 新增的几个- java.net 包下为网络通信相关的类,可以阅读下
Socket
和HTTPClient
相关代码
源码量那么大,不要妄想一口气都看完。最好符合你当前的目的,比如你想搞懂多线程,你就主要看 JUC,想搞懂 IO 就多去看 NIO,想看常量池就去看 ClassFileParser。看模块的时候,要注意接口大于一切,或者说函数大于一切。先不要妄想搞懂所有细节,先找几个比较关键的函数,搞懂函数的作用(比如应该仔细分析一下函数名称和参数名称)然后再往下进行。
在看 Java 类库的时候要多注意类是不是 abstract 的,是不是用的模板方法,多关注函数前的修饰词,这一般说明这个函数是给谁用的。多注意这些细节而不是傻傻过一遍逻辑,能从里面学到不少关 于设计的东西。还可以注意什么地方是为了之前的设计而委曲求全的做法,毕竟一个这么多年的类库,肯定不是什么地方都是完美的。
JDK 源码一定要看 Java 并发相关的源码, Doug Lea 的并发源码比较漂亮,一行行都是精华,非常值得阅读学习。
Spring
Spring 是一个开源的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。包括在此基础上衍生的 Spring MVC、 Spring Boot 、Spring Cloud 等,在现在企业中的应用越来越广泛。无论是设计思想,代码规范,还是设计模式,接口设计,类加载,都是非常优秀的源码。
个人学习心得如下:先去看视频,大概熟悉一下 Spring 的使用情况,然后再去学习源码,此处可以阅读《Spring 源码深度解析》,除了看书之外,记得打开 IDEA 查看对应的源码,如果能调试看看具体调用逻辑那就更好了。
Google Guava
Google Guava 是 Google 公司内部 Java 开发工具库的开源版本。Google 内部的很多 Java 项目都在使用它。它提供了一些 JDK 没有提供的功能,以及对 JDK 已有功能的增强功能。其中就包括:集合(Collections)、缓存(Caching)、原生类型支持(Primitives Support)、并发库(Concurrency Libraries)、通用注解(Common Annotation)、字符串处理(Strings Processing)、数学计算(Math)、I/O、事件总线(EventBus)等等。
Netty
Netty 是一个优秀的开源网络编程框架,我们平常经常接触的 Dubbo、RocketMQ、Elasticsearch、gRPC 等等都用到了 Netty。
Netty 中使用了大量的设计模式以及优秀的设计原则。
Dubbo
Dubbo 是一款优秀的国产 RPC 框架,其 SPI 自适应扩展、负载均衡实现、集群实现、服务调用过程等部分的源码都非常值得阅读和学习。
保姆级别的源码阅读教学
如何高效阅读项目源码
⚠️ 注意:
- 阅读源码之前,一定要先熟悉项目。你连 Dubbo 怎么使用、RPC 是个啥都不知道,就直接去看 Dubbo 源码的话,不是纯属扯淡么?
- 阅读源码之前,一定要对项目源码使用的技术有一个最基本的认识。