当前位置: 首页 > 科技观察

杂谈:我是怎么看源码的,教我看源码的心得

时间:2023-03-20 10:25:39 科技观察

刚开始工作的时候,以前都不想看源码,更不想改源码框架;一直觉得别人的框架应该很好,功能齐全,应该没必要改;另外,即使我更改了源代码,如何让我的更改生效?项目中引用的jar包不还是没有变吗?现在回想起来,我觉得当时的想法真的很好……工作一年多后,我准备跳槽,开始了一轮面试。几个面试官问了相关源码问题:ArrayList、HashMap的底层实现、spring和mybatis的相关源码。关于源码的面试一般都是回去等消息,然后就没有了。那时候开始意识到源码在之前的工作中是没有感觉的,但是在面试的时候好像挺频繁的。从那时起,我就有意识地开始阅读jdk的部分源码(主要是集合)。一开始看源码,很粗糙。我知道一个大概的想法。我知道ArrayList的底层实现是数组,HashMap的底层实现是哈希表(数组+链表);更深层次的扩展,hash碰撞等我就不知道了。读spring源码是在工作中遇到问题时开始的(springjdbcTemplate事务,各种奇奇怪怪的东西,你开悟吧!),经过一段时间的摸索,终于解决了,但是过程让我很不爽。试了一下,感觉就像大海捞针,无处可寻。下定决心,我要看看spring的源码,于是买了一本《spring源码深度解析》,结合这本书,打开eclipse,开始了spring源码的阅读之旅。至此,阅读源码已经成为一种习惯,源码已经走进了我的心里。我为什么要阅读源代码?想必很多人都有和我一样的感受:源码在工作中有用吗?有用吗?这只是他们的水平。那为什么还要看源码呢?一开始是为了面试,后来是为了解决工作中的问题,再后来就是个人喜好了。说好听一点就是要有工匠精神;说好听点就是好奇(底层是怎么实现的);说是不自信,因为我对黑盒的东西没有经验,怕用错;简单直白的说就是提高自我价值,争取更高的薪水(这里真技术粉见谅)。我们可以从源码中学到很多东西,比如学习别人高效的代码编写,学习别人对设计模式的熟练运用,学习别人对整个架构的布局等等。如果你还能找出不足,那么恭喜你,即将飞升!知道如何使用它很重要,但知道为什么以这种方式使用它也很重要。在模仿中学习,在模仿中创新。读源码不是围城(外面的人想进来,里面的人想出去),是外面的人不想进来,里面的人不想出去;当我们踏入城市,你会发现(还是在城外更好,皮肤!)城市里的风景更好,我们可以畅游在源码的海洋里!你决定进城了吗?如何阅读源代码的内容?自己并不了解对方,只是想进入别人的内心世界。这不是又臭又无耻吗?.那么怎么理解呢?有很多方法。我会在这里提供几个。更好的参考方式是官方的参考指南。亲生父母往往最了解自己的孩子,他们的描述也最详细;比如SpringBootReferenceGuide是对springboot最详细的描述,springboot的使用方法,springboot的特性等等,通过这个指南,springboot就可以一目了然;不过springboot毕竟是老外的孩子。如果英文不好,读起来可能有点吃力。头疼,不过我们有谷歌翻译,咬牙也能看懂。源码界的婆婆和老岳父大手笔!二是书籍。外国的好书很多,中国也不乏好书。这就像源码最好的朋友,非常了解源码,关键是她很大方,会尽最大努力帮助我们理解源码。另一个是博客。虽然你可能会觉得知识点比较分散,但是对于某个知识点来说非常详细,对于掌握透彻很有帮助。园内有很多技术高手,写的博客自然很好,很值得学习。价值。当然还有社区、论坛、github、码云等等。这是源码的朋友圈,我们也可以从中获取很多源码的信息。对设计模式的理解优秀的框架和技术从不缺少设计模式;jdk源码中应用了很多设计模式,比如IO流中的适配器模式和装饰模式,GUI中的观察者模式,集合中的迭代器模式等;spring源码中也使用了大量的设计模式。设计模式有哪些优势,适用于哪些场景,不是本文的内容,大家需要自己去了解。我们只需要对一些常用的设计模式有一个大概的了解,再去阅读源码就好了;我们不需要通读所有23种设计模式,也不需要完全理解常用的设计模式;有限的。另外,有些花样确实不太好理解,很少用到,性价比不高。无需全部阅读。推荐书籍:《Head First Design Patterns》(中文版:《Head First 设计模式》)、《Java与模式》;常见的设计模式:单例模式、工厂模式、适配器模式、装饰模式、外观模式、代理模式、迭代器模式、观察者模式、命令模式我推荐的另一种学习设计模式的方法是看别人的博客:java_my_life,刘伟的技术博客,chenssy的设计模式;设计模式之于源码,就像逛街之于女人,想要顺利勾搭源码,就需要掌握设计模式的套路。配合ide进行断点跟踪。我们通过源码圈对源码的了解终究只是表面的,终究没有走进她的内心。接下来就和大家分享我是如何走进她的心的吧!相信看过我的源码博客的朋友都知道,我非常喜欢通过idea断点来追踪源码。断点跟踪源代码是我强烈推荐的一种方式。断点不仅可以用来调试我们的代码,还可以用来调试我们使用的框架源码。面对未知的、浩如烟海的源代码,我们往往没有足够的时间、经验和耐心去阅读所有的源代码。我们只需要阅读我们关心的部分(可能有人会说我不关心,这个。。。)。那为什么要用断开调试的方式跟进源码,而不是直接从源码开始跟进我们关心的部分呢?尝试过的朋友应该知道,如果我们对源码不熟悉的话,可以直接照着源码看。一方面容易迷路(多态性,子类实现会有很多),不知道接下来要走哪一个。另一方面,也很容易迷路。当我们深入跟进的时候,可能会忘记上一步到底去了哪里?下面我将举例说明我是如何跟踪断点的。spring-boot-2.0.3的quartz集成不是你想的那样!与spring-boot-2.0.3的quartz集成,数据源问题,对于源码探索的背景,需要明确两点:springboot如何向quartz注入数据源,quartz如何操作数据库springboot注入数据源成石英。QuartzAutoConfiguration是springboot自动配置quartz的入口。到SchedulerFactoryBean;设置数据源为SchedulerFactoryBean:如果有@QuartzDataSource修改的数据源,则设置@QuartzDataSource修改的数据源为SchedulerFactoryBean,否则设置应用数据源(druid数据源)为SchedulerFactoryBean,显然我们的应用如果没有@QuartzDataSource修饰的数据源,那么SchedulerFactoryBean中的数据源就是应用程序的数据源;将事务管理器设置为SchedulerFactoryBean。SchedulerFactoryBean,负责创建和配置quartzScheduler,并将其注册到spring容器中。SchedulerFactoryBean实现了InitializingBean的afterPropertiesSet方法,有设置数据源的过程。可以看到org.quartz.jobStore.dataSource设置的dsName(valuequartzDs)会被springTxDataSource代替。添加调度器实例名称(在我们的应用程序中是:springTxDataSource.quartzScheduler)。springboot会向quartz注册两个ConnectionProvider:一个dsName叫springTxDataSource.quartzScheduler,里面有事务;一个dsName叫做springNonTxDataSource.quartzScheduler,它没有事务。quartz是如何操作数据库的我们停止定时任务跟随quartz对数据库的操作,发现quartz使用如下方法获取connectionconn=DBConnectionManager.getInstance().getConnection(getDataSource());那么我们的job就可以像下面这样操作数据库了portspringframework.scheduling.quartz.javaBean.Quartz;.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.SQLException;publicclassFetchDataJobextendsQuartzJobBean{//privateStringdataSourceName="quartzDs";//这样会找不到//privateStringdataSourceName="springNonTxDataSource.quartzScheduler";//不支持事务//privateStringdataSourceName="springTxDataSource.quartzScheduler";//支持事务privatefinalStringinsertSql="INSERTIINTOtbl_sys_user(name,age)VALUES(?,?)";privateStringschedulerInstanceName="quartzScheduler";//可以通过jobDataMap注入@OverrideprotectedvoidexecuteInternal(JobExecutionContextcontext)throwsJobExecutionException{StringdsName=LocalDataSourceJobStore.NON_TX_DATA_SOURCE_PREFIX+schedulerInstanceName;//不支持事务//StringdsName=LocalDataSourceJobStore.TX_DATA_SOURCE_PREFIX+schedulerInstanceName;//支持事务try{Connectionconnection=DBConnectionManager.getInstance().getConnection(dsName);PreparedStatementps=connection.prepareStatement(insertSql);ps.setString(1,"张三");ps.setInt(2,25);ps.executeUpdate();ps.close();connection.close();//会连接返回连接池System.out.println("insertsuccessful");}catch(SQLExceptione){e.printStackTrace();}}publicvoidsetSchedulerInstanceName(StringschedulerInstanceName){this.schedulerInstanceName=schedulerInstanceName;}}明确我们的目的,发现右边很容易进入断点,调试和跟踪。我说你还是无动于衷。那只是我的一厢情愿。这其中的奥妙只有游戏中的人才能明白!总结感悟从上到下通读个人不推荐。它基于熟悉度。当我们熟悉了某个框架后,我们可以从上到下通读一遍,理解透彻。我认为这是正确的方法;但是如果你对这个过程不熟悉的话,我个人不建议全部看完,而是推荐我上面推荐的方法——断点局部跟踪。很多时候,我们的博文只是授之以渔,而我们只从他们那里得到鱼;而这篇文章的目的就是授人以渔,希望大家可以从中学会钓鱼,而不是一味等着别人钓鱼;希望每个人都能自给自足,也能授人以渔。只要我们开始阅读源码,就会逐渐形成自己的阅读源码方式;每个人的方式都不一样,适合自己的才是更好的。行动起来,用合适的方式俘获你的少女心!