一、程序员的层次划分(本文只针对学习源码部分)
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、或做过一些项目。