如何学习源码

时间:2024-04-16 20:07:43

一、程序员的层次划分(本文只针对学习源码部分)
  1、只关注项目本身,不懂就baidu一下。
  2、除了做好项目,还会阅读和项目有关的技术书籍,看wikipedia。
  3、找一些开源项目看看,大量试用第三方框架,还会写写demo。 (要解决什么问题?如何实现的?)
      最适合看源码的就是,你对完成一个功能感兴趣,所以你想要了解他。
      比如说Mybatis,你想了解他的代码生成机制,自己先去思考,如果是你做,该怎么做,再去看源码。
      再比如说Log4j.打日志的时候是异步的吗?如果我需要把日志打到另外一台机器上,我该怎么做?
      带着这些问题去思考解决方案。那么天底下的源码都是你的老师。千万别东一锤子西一锤子的去瞎看。
  4、阅读基础框架、J2EE规范、Debug服务器内核。
二、源码学习
1、Java源码初接触 
  在eclipse中加入jdk源码
  (1)点 “window“-> “Preferences”-> “Java” -> “Installed JRES”;
  (2)此时"Installed JRES"右边是列表窗格,列出了系统中的JRE 环境,选择你的JRE,然后点边上的“Edit...“, 会出现一个窗口(Edit JRE) ;
  (3)选中rt.jar文件的这一项:“C:\Java\jdk1.5.0_04\jre\lib\rt.jar” 点 左边的“+”号展开它(JDK实际安装路径以你的为准);
  (4)展开后,可以看到“Source Attachment:(none)”,点这一项,点右边的按钮“Source Attachment...“,选择你的JDK目录下的 “src.zip”文件;
  (5)一路点“ok”结束。

  可以从JDK的util包开始,也就是我们学的《数据结构和算法》Java版,如List接口和ArrayList、LinkedList实现,HashMap和TreeMap等。
  这些数据结构里也涉及到排序等算法,一举两得。 面试时,考官总喜欢问ArrayList和Vector的区别,你花10分钟读读源码,估计一辈子都忘不了。

  然后是core包,也就是String、StringBuffer等。
  如果你有一定的Java IO基础,那么不妨读读FileReader等类。看看《Java In A Nutshell》,里面有整个Java IO的架构图。
  Java IO类库,如果不理解其各接口和继承关系,则阅读始终是一头雾水。
  Java IO 包,我认为是对继承和接口运用得最优雅的案例。如果你将来做架构师,你一定会经常和它打交道,如项目中部署和配置相关的核心类开发。

2、Java Web开发源码
  在阅读Tomcat等源码前,一定要有一定的积累。也可以说是比较好的阶梯是:
  (1)写过一些Servlet和JSP代码。注意,不是用什么Struts,它是很难接触到Servlet精髓的。用好Struts只是皮毛。
  (2)看过《Servlet和JSP核心编程》
  (3)看过Sun公司的Servlet规范
  (4)看过http协议的rfc,debug过http的数据包
  如果有以上基础,也不建议你开始读Tomcat源码。在阅读Tomcat源码前,读过Struts源码,Struts源码比WebWork要简单得多。这个框架是可以100%读懂的,至少WebWork我没有100%读懂。
  如果你读过Struts,再开始考虑Tomcat源码阅读吧。
  不过,还是不建议直接读它,先读读onJava网站上的系列文章《How Tomcat Works》吧,它才是Tomcat的最最简易版。
  它告诉你HttpServletRequest如何在容器内部实现的,Tomcat如何通过Socket来接受外面的请求,你的Servlet代码如何被Tomcat容器调用的(回调)。
  学习JSP,一定要研读容器将JSP编译后的Servlet源码。


3、Java数据库源码阅读
  先读读Sun的JDBC规范。然后编写JDBC的代码。
  如果了解JDBC规范(接口),那么它的实现,JDBC Driver就一定要开始了解,先读读mysql的jdbc驱动,因为它开源、设计优雅。
  在读mysql的JDBC驱动源码时,建议看看mysql的内幕,官方正好有本书《Mysql Internals》。可以知道mysql的JDBC驱动,如何通过socket数据包(connect、query),给这个C++开发的mysql服务器交互的。
  通过上面的阅读,你可以知道,你的业务代码、JDBC规范、JDBC驱动、以及数据库,它们是如何一起协作的。
  如果你了解这些内幕,那么你再学习Hibernate、iBatis等持久化框架时,就会得心应手的。

4、Java通讯及客户端软件
  推荐即时通讯软件wildfire和Spark。你可以把wildfire理解成MSN服务器,Spark理解成MSN客户端。它们是通过XMPP协议通讯的。
  我之所以推荐它们。是因为:
  (1)XMPP够轻量级,好理解
  (2)学习Socket通讯实现,特别是C/S架构设计
  (3)模块化设计。它们都是基于module的,你既可以了解模块化架构,还可以了解模块化的技术支撑:Java虚拟机的ClassLoader的应用场景。
  (4)Event Driven架构。虽然GUI都是Event驱动的,但Spark的设计尤其优雅

5、Java企业级应用
  在读Spring源码前,一定要先看看Rod Johnson写的那边《J2EE Design and Development》,它是Spring的设计思路。注意,不是中文版,中文版完全被糟蹋了。

  “为什么要有这样的架构”,“他是什么样子的”,“他是怎么工作的”。

  IoC容器存在的原因在于对象的解耦,简单来说就是我们自己定义我们要怎么去实现对象中调用的接口。我们做的不就是容器嘛(用新的方式来管理类,那就是容器),我们就定义一个读文件的方法,然后把读到的内容用加载器进行加载,然后放在一个容器里面,名字对应Object,然后开始注入了,我们定义了注入类的位置和被注入类的位置(约定优于配置),我们就去容器中获取。

  ApplicationContext ct=new ClassPathXmlApplicationContext("applicationContext01.xml");    ct.getBean("");

  ClassPathXmlApplicationContext这是东东是我们用来读文件的,可以读配置的文件的类不计其数,只取一个分析,足矣。
  ClassPathXmlApplicationContext这个东东,我们可以追踪他的祖先,AbstractXmlApplicationContext、AbstractRefreshableConfigApplicationContext、AbstractRefreshableApplicationContext、AbstractApplicationContext、DefaultResourceLoader、ResourceLoader,这么多类,一般只读第一个和最后一个,老祖先可以知道它的根基,
  public interface ResourceLoader {
      String CLASSPATH_URL_PREFIX = "classpath:";
      Resource getResource(String var1);
      ClassLoader getClassLoader();
       }

  很明显啊,老祖先ResourceLoader 就是干了这么三件事嘛,定义了加载地址,第二,定义了资源加载的方法,第三,定义了类加载器。
  我们来看下一个重要的类吧。那就是getBean()接口提供类。(ctrl+鼠标左键进入)

  public interface BeanFactory {
       String FACTORY_BEAN_PREFIX = "&";
       Object getBean(String var1) throws BeansException;
       <T> T getBean(String var1, Class<T> var2) throws BeansException;
          <T> T getBean(Class<T> var1) throws BeansException;
       Object getBean(String var1, Object... var2) throws BeansException;
       <T> T getBean(Class<T> var1, Object... var2) throws BeansException;
               boolean containsBean(String var1);
          boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
               boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
          boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
              Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
         String[] getAliases(String var1);
  }

  BeanFactory 很明显就是类的工厂。我们的Resource经过ResourceLoader的调和,用ClassLoader加载,最后变成了BeanFactory。这又是一个粗路线了。
  我们想想资源是不是都需要定义和约束,于是有了BeanDefinition,我们需要封装,于是有了各种**wrapper。
  我们再来想想细节吧,比如说循环注入问题,A引用B,B引用A,那么怎么吧,那不是循环插入到爆炸?那么Spring是怎么实现的。
  我们越想越多,越来越有一种感觉就是,也许那么一刻,那些编程大师,那时候也和你一样这样低头沉思。保持这样的思考,画图,擦涂,重构,最后就是一个能和别人说的思想(架构)。
  在读Hibernate源码前,一定要读读Gavin King写的那本《Hibernate in Action》,同时,应该再读读Martin Fowler写的《企业应用架构模式》,它专门谈到持久化框架的设计思路。

  当你觉得这两本书读透了,再去看它们源码吧。 而且,在读源码前,你会发现它们用到很多第三方Jar包,二三十个,你最好把那些Jar包先一个个搞明白。

  说到企业应用,一定会涉及到工作流。读工作流源码,前提是一定要对其理论模型有深入的了解,以及写过一些demo、或做过一些项目。