本文接上篇文章跟你们聊聊咱们为何要学习源码?学习源码对咱们有用吗?,那么本篇文章再继续跟小伙伴们聊聊源码这个话题。html
在工做之余开始写SpringBoot源码分析专栏前,跟小伙伴们聊聊“分析开源项目源码,咱们该如何入手分析?”这个话题,咱们就随便扯皮,反正是跟小伙伴们一块儿学习交流,不必太正式。java
小伙伴们看完本文后,如有本身的源码阅读心得能够在下面进行评论或私聊我进行分享,让我从小伙伴们身上GET多点源码阅读的一些技巧,嘿嘿。web
那么,先跟小伙伴们聊聊学习开源框架源码的感觉,请问大家认为学习开源框架源码到底难不难?这是一个开放的话题,可谓仁者见仁,智者见智。有一些开源大牛们会说,So easy!;有一些有源码阅读习惯且工做多年的小伙伴们会说,还好。;有一些刚开始学习源码的小伙伴们会说,太难了!。是的,不一样工做经验不一样技术层次的人的回答是不同的。算法
那么刚开始学习开源项目源码难不难呢?应该对绝大部分小伙伴们来讲应该是偏难的。为何呢?可能有如下四点缘由:spring
有些开源框架可能集操做系统知识,数据结构,算法和设计模式于一身。是的,优秀的框架一定是集成了不少设计模式于一身,目前为止笔者还没见过哪一种流行的又没有应用设计模式的框架哈。好比不少框架运用了单例模式,工厂模式,责任链模式,装饰器模式和模板方法模式等,由于使用设计模式能让框架易于扩展。同时,不乏一些框架应用了一些操做系统层面的知识,这一块比较底层,相信不少学java的小伙伴没接触过。此外,开源框架某些地方会用到数据结构和算法,举个栗子,好比Dubbo默认有四种负载均衡策略,而每种策略又对应一种算法,其中又数RoundRobinLoadBalance负载均衡策略最复杂,一开始实现RoundRobinLoadBalance负载均衡的方式并不太完美或者说有bug,Dubbo也是重写过RoundRobinLoadBalance几回,最终借鉴了Nginx的RoundRobinLoadBalance负载均衡算法。apache
上篇文章《跟你们聊聊咱们为何要学习源码?学习源码对咱们有用吗?》也说过优秀框架之间的思想都是互相借鉴的,这就是咱们要学习源码的缘由之一。设计模式
这里好像扯的有点远了,总之这里要说明的是阅读优秀框架是有必定难度的。数据结构
前面跟小伙伴们聊了阅读源码的难度,千万不要被吓慌了。不能否认,刚开始阅读某个开源项目的源码是有必定的难度。注意,前面的用词是刚开始,刚开始哈。也就是说若是咱们坚持阅读源码的话,养成阅读源码是陶冶情操的习惯的话,长期坚持下来再去阅读其余项目的源码,游刃有余不敢说,但确定能够很快入手。mvc
那么,咱们该如何入手去分析开源框架源码呢?负载均衡
首先,结合前面所说的阅读源码之因此难的缘由,咱们就要有针对性的去克服解决。好比有空多学学设计模式,算法和英语。这些软实力确实对阅读源码有很大帮助。
其次,阅读源码的前提是什么?固然,阅读源码是要创建在会使用的基础上,就像若还不会走路就学骑单车同样,若连用都不会就去钻研源码可能会拔苗助长。
最后,咱们阅读源码要注意一些技巧,如今根据自身经历总结一下相关思路和技巧,以下:
开始阅读源码时,先对框架的模块及其关系有一个总体的认识。咱们要对框架项目的模块和目录要有一个全盘的了解,要知道每一个模块是干吗的,而后要了解模块与模块之间的关系。
举个栗子,好比Dubbo的模块分包核心的主要有如下八个,以下图,咱们要知道最基础的的模块应该是dubbo-common公共逻辑模块,这个模块做为最基础的模块,主要是提供了通用模型和工具类;而后dubbo-remoting是远程通信模块,依赖于dubbo-common模块,至关于Dubbo协议的实现;而dubbo-rpc则是远程调用模块,依赖于dubbo-remoting模块,抽象各类协议,以及动态代理;dubbo-cluster是集群模块,依赖于dubbo-rpc模块,将多个服务提供方假装为一个提供方,包括:负载均衡, 容错,路由等。
分析源码先从父类或父接口开始分析。由于父类或者父接口每每表明了一类功能,这些基类或基类接口每每抽象了各个具体子类共有的属性和行为,一些比较基础的方法都在父类中实现,而后留个模板方法给子类去实现便可(模板方法的应用)。
举个栗子,这里仍是拿Dubbo的负载均衡来讲吧,以下图,LoadBalance是各类负载均衡策略的超级接口,定义了 select 方法用来实现选择哪台机器;而后AbstractLoadBalance是一个抽象类,实现了LoadBalance接口,在覆盖了 select 方法后,其又增长了 calculateWarmupWeight 和 getWeight 权重相关的两个方法,由于这些方法都跟具体的负载均衡策略类有关,故在父类实现了。值得注意的是AbstractLoadBalance抽象类的 select 方法中里留了个给子类覆盖的 doSelect 方法,具体的负载均衡策略将在doSelect中实现。
阅读源码前首先要找到启动类。阅读分析源码时要先从启动类开始,所以找到框架启动的入口很重要。
举个Spring事件监听的栗子。好比咱们如今要知道哪一个监听器监听了ContextRefreshedEvent事件,此时咱们能够经过idea全局搜索"(ContextRefreshedEvent"关键字,获得如下截图:从下图能够看到spring-webmvc模块的FrameworkServlet,spring-context模块的ScheduledAnnotationBeanPostProcessor,和spring-jms模块的JmsListenerEndpointRegistry等类订阅了ContextRefreshedEvent事件,那么在容器刷新的时候这几个类将会监听到ContextRefreshedEvent事件,执行一些初始化逻辑。
最后,咱们学习源码不是为了学习而学习,最理想的效果咱们要学以至用。好比把从源码中学习到的设计模式,接口设计方法,面向对象原则和相关算法等等均可以应用到咱们手头的项目中,这才是咱们学习源码的最终目的,也是源码学习的最理想的效果。可能这里有些小伙伴会说,我平时参与的项目都是业务类的项目,而不是开发基础框架,开发中间件,CRUD比较多,可能学习基础框架的源码对咱们用处不多。其实不是的,只要你有参与项目,学习源码咱们学习的是思想,咱们就能够把源码框架设计中的思想应用到咱们的项目中。
最后的最后,咱们来谈谈坚持,这是最难能难得的。不少大道理咱们都懂,好比要坚持运动,坚持学习,坚持...,但是就是没能坚持下来,包括我本身,嘿嘿。坚持这东西太南了,不过仍是应该给本身立个flag吧,把本身有用到的框架好比SpringBoot,Spring,Mybatis,Dubbo,SpringCloud等框架源码都阅读分析一遍,加油,小伙伴们共勉!
欢迎小伙伴们在评论区补充源码阅读技巧哦,让笔者GET多点技能,嘿嘿。
原创不易,帮忙点个赞呗。
参考:
http://dubbo.apache.org/zh-cn/docs/dev/design.html
--------------------------------我是分隔线-----------------------------------
你们好,我是爱编码的码农,能够说是一枚源码爱好者。上周开始写源码分析文章,跟你们一块儿分享本身的学习心得体会,欢迎关注我,一块儿学习交流。