原創(chuàng):猿天地(微信公眾號(hào)ID:cxytiandi),歡迎分享,轉(zhuǎn)載請(qǐng)保留出處。
在工作中,我相信很多人都有下面這樣的感受:
- 這誰(shuí)的代碼呀,看不下去了
- 這破代碼,一行注釋也沒有
- 這代碼,還沒我寫的好
- 這代碼,有bug吧
- 這代碼,。。。。。。。
是不是很真實(shí),我們往往在看別人代碼的時(shí)候就會(huì)有上面這些想法。我認(rèn)為主要的原因還是大部分看的都是業(yè)務(wù)代碼,而且很多是多年積累下來(lái)的,也沒有重構(gòu),然后一年年的堆邏輯,最后就變成shi山了。
當(dāng)然也有不少的人代碼寫的確實(shí)很好,簡(jiǎn)潔易懂,我們?cè)诳磩e人代碼的時(shí)候要抱著學(xué)習(xí)的態(tài)度去看,同樣的邏輯,看看別人是怎么寫的,為什么這樣寫,如果是自己會(huì)怎么寫,對(duì)比下,這樣的話你就有收獲了。
今天想跟大家聊的話題主要是看開源項(xiàng)目的源碼,因?yàn)闃I(yè)務(wù)代碼大家每天都能看。所以往往只會(huì)去用某些框架,而忽略了它的內(nèi)在。
多看開源項(xiàng)目的源碼是很好的學(xué)習(xí)機(jī)會(huì),特別是當(dāng)你遇到問(wèn)題的時(shí)候,或者想要做一個(gè)什么功能的時(shí)候,如果有其他框架中也有類似功能,那么你就知道怎么做了。
案例一
比如我在做一個(gè)功能,需要集成多種配置中心,如果依賴了Nacos那就用Nacos,如果依賴了Apollo,那就用Apollo。在自動(dòng)裝配的類中就要處理這種沒有依賴的情況,最開始想的就是這樣處理:
@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)目沒有依賴Nacos的情況下,這里就會(huì)報(bào)錯(cuò),雖然加了判斷也不行。這個(gè)時(shí)候我就再想,其他的一些框架中是如何實(shí)現(xiàn)的呢?
這個(gè)時(shí)候我就想到之前看Zuul的源碼,里面也有類似的需求。會(huì)使用不同的Client來(lái)進(jìn)行調(diào)用,比如ApacheHttpClient, OkHttpClient。
發(fā)現(xiàn)Zuul里面是加了靜態(tà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)我也有類似需求的時(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é)
寫本文的目的就是為了告訴大家,在平時(shí)無(wú)事的時(shí)候除了學(xué)習(xí)一些框架的使用,也要去翻翻源碼。雖然當(dāng)時(shí)不一定用的到,但是在你以后遇到類似問(wèn)題的時(shí)候,你會(huì)有映象說(shuō),當(dāng)時(shí)我在某某框架中看到過(guò)類似的解決方案,這就是你的知識(shí)積累。
另一個(gè)點(diǎn)就是這些框架中都會(huì)用到一些好的設(shè)計(jì),也是我們可以學(xué)習(xí)參考的案例。
最后就是在面試中也有遇到說(shuō):有沒有看過(guò)框架的源碼啊之類的問(wèn)題?
如果真的看過(guò),并且記住了,這個(gè)時(shí)候你就可以和面試官侃侃而談,稱兄道弟了。
關(guān)于作者:尹吉?dú)g,簡(jiǎn)單的技術(shù)愛好者,《Spring Cloud微服務(wù)-全棧技術(shù)與案例解析》, 《Spring Cloud微服務(wù) 入門 實(shí)戰(zhàn)與進(jìn)階》作者, 公眾號(hào)猿天地發(fā)起人。