不看源碼,怎么卷的過(guò)小年輕
在工作中,我相信很多人都有下面這樣的感受:
這誰(shuí)的代碼呀,看不下去了 這破代碼,一行注釋也沒(méi)有 這代碼,還沒(méi)我寫(xiě)的好 這代碼,有 bug 吧 這代碼,。。。。。。。
是不是很真實(shí),我們往往在看別人代碼的時(shí)候就會(huì)有上面這些想法。我認(rèn)為主要的原因還是大部分看的都是業(yè)務(wù)代碼,而且很多是多年積累下來(lái)的,也沒(méi)有重構(gòu),然后一年年的堆邏輯,最后就變成 shi 山了。
當(dāng)然也有不少的人代碼寫(xiě)的確實(shí)很好,簡(jiǎn)潔易懂,我們?cè)诳磩e人代碼的時(shí)候要抱著學(xué)習(xí)的態(tài)度去看,同樣的邏輯,看看別人是怎么寫(xiě)的,為什么這樣寫(xiě),如果是自己會(huì)怎么寫(xiě),對(duì)比下,這樣的話你就有收獲了。
今天想跟大家聊的話題主要是看開(kāi)源項(xiàng)目的源碼,因?yàn)闃I(yè)務(wù)代碼大家每天都能看。所以往往只會(huì)去用某些框架,而忽略了它的內(nèi)在。
多看開(kāi)源項(xiàng)目的源碼是很好的學(xué)習(xí)機(jī)會(huì),特別是當(dāng)你遇到問(wèn)題的時(shí)候,或者想要做一個(gè)什么功能的時(shí)候,如果有其他框架中也有類(lèi)似功能,那么你就知道怎么做了。
案例一
比如我在做一個(gè)功能,需要集成多種配置中心,如果依賴(lài)了 Nacos 那就用 Nacos,如果依賴(lài)了 Apollo,那就用 Apollo。在自動(dòng)裝配的類(lèi)中就要處理這種沒(méi)有依賴(lài)的情況,最開(kāi)始想的就是這樣處理:
@ConditionalOnClass(value = com.alibaba.nacos.api.config.ConfigService.class)
@ConditionalOnMissingClass(value = { "com.alibaba.cloud.nacos.NacosConfigProperties" })
@Bean
public NacosConfigUpdateListener nacosConfigUpdateListener() {
return new NacosConfigUpdateListener();
}
然后測(cè)試發(fā)現(xiàn),如果在項(xiàng)目沒(méi)有依賴(lài) Nacos 的情況下,這里就會(huì)報(bào)錯(cuò),雖然加了判斷也不行。這個(gè)時(shí)候我就再想,其他的一些框架中是如何實(shí)現(xiàn)的呢?
這個(gè)時(shí)候我就想到之前看 Zuul 的源碼,里面也有類(lèi)似的需求。會(huì)使用不同的 Client 來(lái)進(jìn)行調(diào)用,比如 ApacheHttpClient, OkHttpClient。
發(fā)現(xiàn) Zuul 里面是加了靜態(tài)類(lèi)進(jìn)行判斷的,這就不會(huì)報(bào)錯(cuò)了。如下:
@Configuration
@ConditionalOnClass(value = com.alibaba.nacos.api.config.ConfigService.class)
@ConditionalOnMissingClass(value = { "com.alibaba.cloud.nacos.NacosConfigProperties" })
protected static class NacosConfiguration {
@Bean
public NacosConfigUpdateListener nacosConfigUpdateListener() {
return new NacosConfigUpdateListener();
}
}
案例二
當(dāng)我需要控制 Feign 的調(diào)用邏輯,替換調(diào)用的 URL 時(shí)我就想到之前看過(guò) Sleuth 的源碼,Sleuth 做為一款鏈路跟蹤框架,內(nèi)部對(duì)很多框架進(jìn)行了集成。
像 Feign 這種遠(yuǎn)程調(diào)用的,需要對(duì)它進(jìn)行擴(kuò)展,然后透?jìng)麈溌犯櫟臄?shù)據(jù)。所以當(dāng)我也有類(lèi)似需求的時(shí)候,就可以參考 Sleuth 的實(shí)現(xiàn)。

上面貼了 Sleuth 中的 TracingFeignClient 源碼,TracingFeignClient 就是 Sleuth 中對(duì) Feign Client 的擴(kuò)展,增加了 Sleuth 自己的一些邏輯。然后這個(gè) TracingFeignClient 最終會(huì)在啟動(dòng)的時(shí)候替換掉 Feign 默認(rèn)的 Client。
案例三
當(dāng)我需要對(duì) Redis 做埋點(diǎn)監(jiān)控的時(shí)候,又想起了之前看過(guò) opentracing 中對(duì) Redis 的監(jiān)控代碼,就可以借鑒里面的方式。
地址:
https://github.com/opentracing-contrib/java-spring-cloud/
里面就是用了 AOP 對(duì) RedisConnectionFactory 和 RedisConnection 進(jìn)行了替換,也不用動(dòng)框架底層的代碼,擴(kuò)展就行。
總結(jié)
寫(xiě)本文的目的就是為了告訴大家,在平時(shí)無(wú)事的時(shí)候除了學(xué)習(xí)一些框架的使用,也要去翻翻源碼。雖然當(dāng)時(shí)不一定用的到,但是在你以后遇到類(lèi)似問(wèn)題的時(shí)候,你會(huì)有映象說(shuō),當(dāng)時(shí)我在某某框架中看到過(guò)類(lèi)似的解決方案,這就是你的知識(shí)積累。
另一個(gè)點(diǎn)就是這些框架中都會(huì)用到一些好的設(shè)計(jì),也是我們可以學(xué)習(xí)參考的案例。
最后就是在面試中也有遇到說(shuō):有沒(méi)有看過(guò)框架的源碼啊之類(lèi)的問(wèn)題?
如果真的看過(guò),并且記住了,這個(gè)時(shí)候你就可以和面試官侃侃而談,稱(chēng)兄道弟了。
關(guān)于作者:尹吉?dú)g,簡(jiǎn)單的技術(shù)愛(ài)好者,《Spring Cloud 微服務(wù)-全棧技術(shù)與案例解析》, 《Spring Cloud 微服務(wù) 入門(mén) 實(shí)戰(zhàn)與進(jìn)階》作者, 公眾號(hào)猿天地發(fā)起人。
