在工作中,我相信很多人都有下面这样的感受:
- 这谁的代码呀,看不下去了
- 这破代码,一行注释也没有
- 这代码,还没我写的好
- 这代码,有bug吧
- 这代码,。。。。。。。
是不是很真实,我们往往在看别人代码的时候就会有上面这些想法。我认为主要的原因还是大部分看的都是业务代码,而且很多是多年积累下来的,也没有重构,然后一年年的堆逻辑,最后就变成shi山了。
当然也有不少的人代码写的确实很好,简洁易懂,我们在看别人代码的时候要抱着学习的态度去看,同样的逻辑,看看别人是怎么写的,为什么这样写,如果是自己会怎么写,对比下,这样的话你就有收获了。
今天想跟大家聊的话题主要是看开源项目的源码,因为业务代码大家每天都能看。所以往往只会去用某些框架,而忽略了它的内在。
多看开源项目的源码是很好的学习机会,特别是当你遇到问题的时候,或者想要做一个什么功能的时候,如果有其他框架中也有类似功能,那么你就知道怎么做了。
案例一
比如我在做一个功能,需要集成多种配置中心,如果依赖了Nacos那就用Nacos,如果依赖了Apollo,那就用Apollo。在自动装配的类中就要处理这种没有依赖的情况,最开始想的就是这样处理:
@ConditionalOnClass(value = com.alibaba.nacos.api.config.ConfigService.class)
@ConditionalOnMissingClass(value = { "com.alibaba.cloud.nacos.NacosConfigProperties" })
@Bean
public NacosConfigUpdateListener nacosConfigUpdateListener() {
return new NacosConfigUpdateListener();
}
然后测试发现,如果在项目没有依赖Nacos的情况下,这里就会报错,虽然加了判断也不行。这个时候我就再想,其他的一些框架中是如何实现的呢?
这个时候我就想到之前看Zuul的源码,里面也有类似的需求。会使用不同的Client来进行调用,比如ApacheHttpClient, OkHttpClient。
发现Zuul里面是加了静态类进行判断的,这就不会报错了。如下:
@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();
}
}
案例二
当我需要控制Feign的调用逻辑,替换调用的URL时我就想到之前看过Sleuth的源码,Sleuth做为一款链路跟踪框架,内部对很多框架进行了集成。
像Feign这种远程调用的,需要对它进行扩展,然后透传链路跟踪的数据。所以当我也有类似需求的时候,就可以参考Sleuth的实现。
上面贴了Sleuth中的TracingFeignClient源码,TracingFeignClient就是Sleuth中对Feign Client的扩展,增加了Sleuth自己的一些逻辑。然后这个TracingFeignClient最终会在启动的时候替换掉Feign默认的Client。
案例三
当我需要对Redis做埋点监控的时候,又想起了之前看过opentracing中对Redis的监控代码,就可以借鉴里面的方式。
地址:
里面就是用了AOP对RedisConnectionFactory和RedisConnection进行了替换,也不用动框架底层的代码,扩展就行。
总结
写本文的目的就是为了告诉大家,在平时无事的时候除了学习一些框架的使用,也要去翻翻源码。虽然当时不一定用的到,但是在你以后遇到类似问题的时候,你会有映象说,当时我在某某框架中看到过类似的解决方案,这就是你的知识积累。
另一个点就是这些框架中都会用到一些好的设计,也是我们可以学习参考的案例。
最后就是在面试中也有遇到说:有没有看过框架的源码啊之类的问题?
如果真的看过,并且记住了,这个时候你就可以和面试官侃侃而谈,称兄道弟了。