如何学习源码?

如果大家觉得文章有错误内容,欢迎留言或者私信讨论~

  每当我们准备跳槽的时候,都会留意到一些招聘信息里往往写着:研究过框架和中间件源码的优先考虑。这是因为我们 Java 这些本身就作为我们的日常,阅读源码会让我们对框架和中间件的理解更加深刻。有时候即使我们阅读了大量原理性的文档,但如果不看源码,可能仍然会觉得没有理解透。

  对于我们后端来说,有不少经典的开源框架和中间件,如下:

  • 服务接入层: 反向代理 Nginx;
  • 业务逻辑层: Web 容器 Tomcat、Jetty;应用层框架 Spring、Spring MVC 和 Spring Boot;ORM 框架 Mybtais;
  • 数据缓存层: 内存数据库 Redis;消息中间件 Kafka;
  • 数据存储层: 关系型数据库 MySQL;非关系型数据库 MongoDB;文件存储 HDFS;搜索分析引擎 Elasticsearch;

  这其中每一层都要支持水平拓展和高可用,于是业务层普遍采用微服务架构,微服务之间需要互相调用,于是就出现了 RPC 框架: Spring Cloud 和 Dubbo。

  除此之外,还有两个非常重要的基础组件: Netty 和 Zookeeper,其中 Netty 用于网络通信,ZooKeeper 用于分布式协调。很多中间件都会用到这两个组件,并且 ZooKeeper 的网络通信模块也是通过 Netty 来实现的。

  这些框架都不是凭空产生的,而是为了解决具体业务的痛点,一点一点演化而来,我们将他们拼凑在一起就能够搭建一个企业级的互联网后台系统。一般的大厂会对这些框架或者中间件进行改造,甚至是自己来实现,这就对我们从业人员有更高的要求。

  那么市面上这么多的中间件和框架,从哪里入手呢?先学哪个后学哪个?我觉得应该先从熟悉的、简单的入手,比如 Tomcat、 Jetty 和 Spring 核心容器,弄懂了这些就可以拓展到 Spring 的其他组件。

  在这个过程,我们就会逐渐累计一些通用的技术,比如网络编程、多线程、反射和类加载技术等。这些通用技术在不少的框架和中间件中用到。

  先说网络通信,在分布式环境下,信息要在各个实体之间流动,到处都是网络通信的场景,比如浏览器要将 HTTP 请求发给 Web 容器,一个微服务要调用另一个微服务,Web 应用读写缓存服务器、消息队列或者数据库等,都需要网络通信。

  尽管网络通信很多,但无外乎要考虑:

  • I/O 模型同步还是异步,是阻塞还是非阻塞
  • 通信协议是二进制(gRPC) 还是文本(HTTP)
  • 数据怎么序列号,是 JSON 还是 Protocol Buffer

  我们再来看看** Java 反射机制**,几乎所有的框架都用到了反射和类加载技术,这是为了保证框架的通用性,需要根据配置文件在运行时加载不同的类,并调用其方法。比如 Web 容器 Tomcat 和 Jetty,通过反射来加载 Servlet、Filter 和 Listener;而 Spring 的两大核心功能 IOC 和 AOP,都用到了反射技术;再比如 MyBatis 将数据从数据库读出后,也是通过反射机制来创建 Java 对象并设置对象的值。

  因此你会发现,当你熟悉了一个中间件的通用技术之后,再学习其他的中间件或者框架就容易多了。比如学透了 Tomcat 的 I/O 线程模型以及高并发高性能设计思路,再学 Netty 的源码就轻车熟路了;Tomcat 的组件化设计和类加载机制理解透彻了,再学 Spring 容器的源码就会轻松很多。

如何具体的学习源码

  学习的第一步,首先我们要弄清楚中间件的核心功能是什么,比如我现在所学的专栏里就在讲 Tomcat,Tomcat 的核心功能是 HTTP 服务器和 Servlet 容器,因此就抓住请求处理这条线:通过什么样的方式接收连接,接收到连接后以什么样的方式来读取数据,读到数据后怎么解析数据(HTTP 协议),请求数据解析出来后怎么调用 Servlet 容器,Servlet 容器又怎么调到 Spring 中的业务代码。

  为了完成这些功能,Tomcat 中有一些骨架启动核心的作用,其他都是补充作用,我们就可以先建立一个粗略的印象:
在这里插入图片描述
  在此之后,我们还需要将源码跑起来,打打断点,看看变量的值和调用栈。我建议用内嵌式的方式来启动和调试 Tomcat,体会一下 Spring Boot 是如何使用 Tomcat 的。

  我们还要带着问题去学习源码,比如你想弄清楚 Tomcat 如何启停、类加载器是如何设计的、Spring Boot 是如何启动 Tomcat 的、Jetty 是如何通过 Handler 链实现高度定制化的,如果要你来设计这些功能会怎么做呢? 只要你还带着问题去学习,那么你就还有很大的成长空间。

  当然在这个过程中,你还可以看看产品的官方文档,熟悉一下大概的设计思路。在遇到难题时,你还可以看看网上的博客,参考一下别人的分析。但最终还是需要你自己去实践和摸索,因为网上的分析也不一定对,只有你自己看了源码后才能真正理解它,印象才更加深刻。

  如果你理解透彻一两个中间件,有了一定的积累,这时再来学一个新的系统,往往你只需要瞧上几眼,就能明白它所用的架构,而且你会自然联想到系统存在哪些角色,以及角色之间的关系,包括静态的依赖关系和动态的协作关系,甚至你会不由自主带着审视的眼光,来发现一些可以改进的地方。如果你现在就是这样的状态,那么恭喜你,你的技术水平已经成长到一个新的层面了。

猜你喜欢

转载自blog.csdn.net/qq_43654226/article/details/127430482
今日推荐