1. 写在前面
对于做Java开发的同学来说,Spring就像是一条绕不过去的路,但是大多数也只是停留在对Spring的简单使用层面上,对于其背后的原理所知不多也不愿深究,关于这个问题,我在平时的生活及工作中也在不断思考。
为什么要阅读Spring的源码?
- 不是为了读源码而读源码,Spring有很好的设计思想,值得学习;
- Spring是当前使用最广泛的一个开发框架,学习其原理可以帮助我们更好的应对工作中出现的各种框架相关的问题;
- 在开发中越来越多的使用到了各种各样的框架,渐渐的开发人员只会引入jar包进行开发了,对于一些应用底层的问题难以快速解决,阅读源码可以让我们站在一个更高的视角看待我们的开发的工程,对整个系统也能够有更深入的了解,有助于增加自己的深度;
- Spring对很多其它的框架(比如mybatis、springmvc等)提供了很好的集成,学习Spring的原理可以更好的帮助我们理解其他的框架的工作原理,从而对整个系统能够有更深入的了解;
以上只是个人观点,基于此,打算阅读一下Spring源码并将相关读书笔记总结成文,以供后面回顾。所谓磨刀不误砍柴功,要阅读源码,首先我们要有一个源码阅读的环境,所以第一篇文章先来总结一下源码阅读环境的搭建。
2. 构件源码阅读环境
首先声明一些基本配置:这个读书笔记系列中涉及到的开发工具是eclipse,Spring版本为3.2.18.RELEASE,电脑所使用的操作系统为win 10。
阅读Spring源码常用的方式有两种:
- 新建一个工程,引入Spring的jar包,然后直接阅读;
- 下载Spring官方源码并导入到工程中,然后进行阅读;
前者非常便捷,后者逼格更高,而且可以修改源码,两者没有好坏之分,使用哪种从心即可,这里只是记录一下在搭建源码阅读环境的过程中所踩过的坑。
2.1 引入jar包
采用这种方式非常方便,只需要在项目中引入Spring相关的依赖,再简单配置一下,就能阅读源码了。笔者在阅读时是通过maven进行构建工程的,所使用的Spring依赖如下:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.18.RELEASE</version>
</dependency>
这种方式比较简单,对于想阅读Spring源码的同学来说,其简单使用及配置自然是会的,在此就不过多论述这部分了。
2.2 下载官方源码并导入工程
这种方式在我看来就是逼格比较高罢了(可以修改Spring的源码),但是环境的搭建还是要费一番功夫的,笔者当初在这个地方还是费了一些时间的,特在此记录当时踩过的坑,废话有点多,这就开始吧。
Spring的源码是托管在github上,所以我们先需要上网把它下下来。首先输入网址https://github.com/,搜索Spring,本次导入的源码版本为3.2.x,进行排序按照stars多少来选择():
选择版本:
点击下载zip文件:
下载下来后,解压缩得到源码文件:
此时,对应文件夹下已经存在相应的源码了,但是这个源码并不能直接导入Eclipse中,我们还需要将源码转换为Eclipse可以读取的形式。因为源码下面有很多工程,这里建议只对我们感兴趣的工程进行Eclipse工程转换,比如我们想要查看Spring容器部分源码,打开cmd命令窗口,将当前目录切换至源码所在目录,这里是Spring-Context文件夹下,执行命令"gradle cleanidea eclipse"(前提得是要安装了gradle才行,因为Spring的源码是用gradle构建的),当窗口出现如下状态说明已经成功了:
如果提示下面的错误:
Could not get unknown property 'classesDir' for main classes of type org.gradle.api.internal.tasks.DefaultSourceSetOutput
The classesDir property was deprecated in gradle 4.x, and removed in gradle 5.x (see the release notes).
这是由于gradle的版本过高导致,需要切换到4以下,详见 Could not get unknow property 'classesDir' for main classes ...
如果出现如下错误:
Could not find matching constructor for: org.gradle.plugins.ide.eclipse.model.ProjectDependency(org.codehaus.groovy.runtime.GStringImpl,java.long.String)
这也是由于gradle的版本导致,对于的源码中缺少构造器,详见:如何从github上拉取Spring-framwork源码项目,导入到eclipse中。
解决如上问题之后,这时,我们再看对应的文件夹会发现,已经出现了作为Eclipse工程所必须的.project与.classpath文件了,这时就可以打开Eclipse,将工程导入了,导入项目之后相关依赖的项目也需要导入。
导入之后,项目上有个红叹号,右键项目--properties--Java Build Path--Libraries,发现是丢失spring-asm-repack和spring-cglib-repack包,安照下面的步骤来处理:
- 到这个网站下载spring的lib压缩包,我下载的是和源码对应的spring-framework-3.2.18.RELEASE-dist.zip;
- 解压spring-framework-3.2.18.RELEASE-dist.zip 在spring-framework-3.2.18.RELEASE-dist\spring-framework-3.2.18.RELEASE\libs路径下找到spring-core-3.2.18.RELEASE.jar;
- 再把spring-core-3.2.18.RELEASE.jar用压缩工具解压出来;
- 然后cmd到这个目录下执行如下两条命令:
jar cvf spring-cglib-repack-3.1.jar org\springframework\cglib
jar cvf spring-asm-repack-5.0.4.jar org\springframework\asm
命令执行成功后会生成如下jar包:
将这两个jar包导入项目之后,错误就消除了:
这里我们已经导入core,同样的操作,我们导入spring-beans,这里就已经具备基本的IoC功能了,我们可以写点测试代码试试。
beans.xml,配置文件需要放在core项目下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <bean id="testBean" class="test.TestBean">
<property name="name" value="hello"></property>
</bean>
</beans>
下面是测试用例:
public class Test {
public static void main(String[] args) {
/**
* 用XmlBeanFactory这个方式获得bean,现在已经不用这个方式了
*/
XmlBeanFactory xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
TestBean myTestBean = (TestBean) xmlBeanFactory.getBean("myTestBean");
System.out.println( myTestBean+ "---"+ myTestBean.getName());
}
} public class TestBean {
private String name; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}
运行结果:
好啦,如果顺利执行到这一步,那就代表你成功了,接下来你就能对Spring为所欲为了。。
3. 遇到问题
除了上面遇到的问题,还有几个问题记录在这里。
导入spring-context时候遇到问题:Access restriction: The type 'Application' is not API (restriction on required library rt.jar)。
解决办法:右键spring-context工程--properties--Libraries--点开JRE--Access Rules--Edit--Add--添加新规则com/sun/net/**,详见参考文献4,参考如下:
我们瞥一眼beans工程中的代码:
4. 参考文献
1. eclipse导入spring源码二(丢失的spring-asm-repack和spring-cglib-repack)
2. Spring源码下载及安装
3. Build path entry is missing” error when trying to create a new project in Eclipse
4. Access restriction: The type 'Application' is not API (restriction on required library rt.jar)