古希腊语言中,学习一词即为闲暇之意,闲下来了就去学习是一种很好的状态。趁着 2020 年春节假期,过一把闻名已久的 Spring 源码之瘾。

源码下载

官方资料

阅读源码的关键资料,当然是官方文档和官方源代码:

Spring Framework 官网文档:https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html

Spring Framework 开放源代码:https://github.com/spring-projects/spring-framework

下载过程

Windows 10 安装 Git,从 github 克隆的话比较慢,我借助码云从 github 导出了一份,再从码云上拉取,速度好极了。码云还提供手动同步 github 源码的功能,我搬运的一份:https://gitee.com/blackist/spring-framework

克隆下来的源码只有 master 分支,为阅读指定版本的源码 5.0.x,需要拉取指定分支:

1
git fetch origin 5.0.x:5.0.x

即拉取远程的 5.0.x 到本地,然后手动切换至 5.0.x 再导入:

1
git checkout 5.0.x

源码导入

环境配置

  • java version “1.8.0_162”
  • IntelliJ IDEA 2018.3

源码工程是基于 Gradle 构建的, gradle 版本由源码配置文件指定。

IDEA 导入源码

首先执行 gradlew 编译任务:

1
gradlew.bat cleanIdea :spring-oxm:compileTestJava

Import project -> Import project from external model (选择 gradle) -> Next … Finish

IDEA 会根据 ./gradle/wrapper/gradle-wrapper.properties 中指定版本下载 gradle,gradle 路径为 {user}/.gradle/wrapper/dists,各版本的 gradle 都会在这里(搞安卓开发的小伙伴有没有很熟悉)。

等待 gradle 构建完成。

测试代码

新建 Gradle 模块

为进行简洁的测试,新建一个 Gradle 模块,在模块中依赖 spring-beans、spring-aop 等模块,可更直观的阅读源码。

右键项目 -> New -> Module,

选择 Gradle,

ArtifactId 填写自定义名称 code-quiz 等等,Module Name 也会默认是 code-quiz,Finish。

新建模块的结构如上,这个 build.gradle 就类似 maven 的 pom.xml,是此模块的配置文件。在 dependencies 中依赖 spring-core、spring-beans,就可以实现 IoC了。当然,也可以直接依赖 spring-context 实现 IoC,但我从最基本的模块开始学习。

测试代码

新建 java bean,通过 xml 文件配置 bean,并新建工厂获取 bean。

资源文件 quiz-bean.xml 放在 resources 目录下,并配置 QuizBean 的信息:

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="ISO-8859-1"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<bean id="quizBean" class="bean.QuizBean"/>
</beans>

新建 XmlFactoryBeanTests 进行测试:

1
2
3
4
5
6
7
8
9
public class XmlBeanFactoryTests {

public static void main(String[] args) {

BeanFactory factory = new XmlBeanFactory(new ClassPathResource("bean/quiz-beans.xml"));
QuizBean quizBean = (QuizBean) factory.getBean("quizBean");
System.out.println(quizBean.getName());
}
}

编译错误

运行 XmlBeanFactoryTests 中的 main 函数,会出现如下编译错误:

原因:为了避免第三方 class 冲突,spring 把最新的 cglib 和 objenesis 重新打包 jar 并没有放在源码里。

解决办法:在命令行中执行 gradle 的构建任务 objenesisRepackJar 和 cglibRepackJar。但需要先配置 gradle 环境变量。

1
gradle objenesisRepackJar cglibRepackJar

gradle 配置

配置 gradle 环境变量类似于 maven,就是将 gradle 的下载路径配置到系统的环境变量,但不同的 gradle 工程往往 gradle 版本不一样,因此配置固定版本的 gradle 到环境变量会给其他项目带来不便。

gradle 项目构建时,一般会生成一个 gradlew 的 bash 脚本文件,它会根据项目所需的 gradle 去默认目录使用 gradle 命令,因此直接执行如下命令即可:

1
gradlew objenesisRepackJar cglibRepackJar

执行结果如下:

其他问题

  1. 执行 gradlew 命令时,提示 ERROR: JAVAHOME is set to an invalid directory: C:\Program Files\Java\jdk1.8.0 131,原因是 JDK 路径确实有问题,我安装过两个 JDK,以前的版本删除了,但环境变量没改,给IU改几颗。
  2. main 函数中工厂基于 xml 文件构建,代码运行时提示找不到 xml,以为路径问题,反复折腾无效,偶然间重启电脑解决了问题,估计是 idea 工程缓存问题。

慢慢读源码啦。

参考

https://blog.csdn.net/a704397849/article/details/102760379

https://blog.csdn.net/u010999809/article/details/94293328

(完)