前言

最近稍微研究了一下Spring源码,将源码拉到本地,可以自己编译和调试,也可以自己直接在源码里面写注释。本文记录整个过程和遇到的问题。

运行环境

  • Operating system : MacOS Monterey 12.3
  • IDEA : IntelliJ IDEA 2021.3
  • gradle : 5.6.4
  • spring-framework : 5.2.22.RELEASE
  • jdk : 11.0.15

下载源码和搭建gradle环境

下载源码

在github上搜索spring-framework,下载spring的官方源码。当然也可以下载本人仓库添加过中文注释的spring-framework-5.2.22.RELEASE。如果github下载缓慢,可以尝试国内gitee镜像。

进入官方github的spring-framework项目主界面,建议选择最新的RELEASE版本进行下载。

java spring 调试 如何调试spring源码_spring

点击右侧的Releases进入对应版本页面,这里我选择的是v5.2.22.RELEASE版本下载。选择.zip格式文件的文件下载就可以。这里值得注意的是,网上很多帖子不建议直接下载.zip文件,因为会遇到编译报错,我在解决git报错信息给出了解决方案。

java spring 调试 如何调试spring源码_java spring 调试_02

当然也可以直接通过git clone方式进行获取源码,这里我就不过多赘述。

zhangyao@MacBookPro ~ % git clone https://github.com/spring-projects/spring-framework.git

下载解压后整个文件的目录结构如下所示,我圈出了几个我们需要了解和修改几个文件。

java spring 调试 如何调试spring源码_java spring 调试_03

1.import-into-idea.md,官方提供的spring源码导入idea的步骤和注意说明,感兴趣可以看看别人已经翻译的文章。

2.settings.gradle,在里面替换国内的阿里云maven仓库。(我有梯子我没换)

maven { url "https://maven.aliyun.com/repository/public" }

3.修改gradle.properties文件。

version=5.2.22.RELEASE
org.gradle.jvmargs=-Xmx1536M
org.gradle.caching=true
org.gradle.parallel=true

## 启用新的孵化模式
org.gradle.configureondemand=true
## 开启守护进程 通过开启守护进程,下一次构建的时候,将会连接这个守护进程进行构建,而不是重新fork一个gradle构建进程
org.gradle.daemon=true

## 这个配置是指定我们的jdk目录
org.gradle.java.home=/Users/zhangyao/Library/Java/JavaVirtualMachines/corretto-11.0.15/Contents/Home

MacBook Pro查看jdk路径的方法,使用命令/usr/libexec/java_home -V

zhangyao@MacBookPro ~ % /usr/libexec/java_home -V Matching Java Virtual Machines (2): 11.0.15 (x86_64) "Amazon.com Inc." - "Amazon Corretto 11" /Users/zhangyao/Library/Java/JavaVirtualMachines/corretto-11.0.15/Contents/Home 1.8.0_261 (x86_64) "Oracle Corporation" - "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_261.jdk/Contents/Home /Users/zhangyao/Library/Java/JavaVirtualMachines/corretto-11.0.15/Contents/Home zhangyao@MacBookPro ~ %

4.修改build.gradle文件,使用阿里云仓库,提高下载速度。(我有梯子我还没换)

maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter'}

Gradle环境

zhangyao@MacBookPro spring-framework % ./gradlew -v

Welcome to Gradle 5.6.4!

Here are the highlights of this release:
 - Incremental Groovy compilation
 - Groovy compile avoidance
 - Test fixtures for Java projects
 - Manage plugin versions via settings script

For more details see https://docs.gradle.org/5.6.4/release-notes.html


------------------------------------------------------------
Gradle 5.6.4
------------------------------------------------------------

Build time:   2019-11-01 20:42:00 UTC
Revision:     dd870424f9bd8e195d614dc14bb140f43c22da98

Kotlin:       1.3.41
Groovy:       2.5.4
Ant:          Apache Ant(TM) version 1.9.14 compiled on March 12 2019
JVM:          11.0.15 (Amazon.com Inc. 11.0.15+9-LTS)
OS:           Mac OS X 12.3 x86_64

zhangyao@MacBookPro spring-framework %

构建源码

预编译spring-oxm&spring-core

如果结果中有BUILD SUCCESSFUL字样就说明预编译成功。MacOS下输入如下命令:

zhangyao@MacBookPro spring-framework-5.2.22.RELEASE % ./gradlew :spring-oxm:compileTestJava
zhangyao@MacBookPro spring-framework-5.2.22.RELEASE % ./gradlew :spring-core:compileTestJava

java spring 调试 如何调试spring源码_java spring 调试_04

导入项目

Idea中,import project ,然后选择源码主目录下的build.gradle,然后导入。配置本地的grade :

java spring 调试 如何调试spring源码_java_05

导入后,会进行configure build,过程很漫长。还是找BUILD SUCCESSFUL字样。

开始构建

Reload All Gradle Projects

点进Gradle右上角进行重新载入项目,耐心等待编译完成。还是找BUILD SUCCESSFUL字样。

java spring 调试 如何调试spring源码_java_06

测试验证

搭建测试Module

在spring源码项目中新建一个module,File–>New–>Module。

java spring 调试 如何调试spring源码_gradle_07

选择Gradle项目。

java spring 调试 如何调试spring源码_java spring 调试_08

我给项目起名叫做spring-debug,毕竟我是为了读源码,debug关键方法进行阅读。

java spring 调试 如何调试spring源码_intellij-idea_09

项目创建完成后,spring源码项目会多一个spring-debug模块,在build.gradle中添加依赖就可以为所欲为的调试spring源码了。

compile(project(":spring-context"))

java spring 调试 如何调试spring源码_gradle_10

问题解决

前面有说到这个过程我们可能会遇到各种个样的的问题,比如:

Git报错问题

下载解压.zip文件导入项目出现git报错的问题,报错信息如下图所示,相信很多人和我一样都会遇到过。之后我搜了网上很多帖子都是建议使用git clone方式获取源码就不会报这个错了。我也尝试了使用git clone的方式然后导入,确实不会出现这个问题。之后我灵机一动,想着我在解压到的spring-framework初始化一个空的git本地仓库,效果会怎么样?

java spring 调试 如何调试spring源码_intellij-idea_11

Build scan background action failed.
org.gradle.process.internal.ExecException: Process 'command 'git'' finished with non-zero exit value 128
	at org.gradle.process.internal.DefaultExecHandle$ExecResultImpl.assertNormalExitValue(DefaultExecHandle.java:409)
	at org.gradle.process.internal.DefaultExecAction.execute(DefaultExecAction.java:38)
	at org.gradle.process.internal.DefaultExecActionFactory.exec(DefaultExecActionFactory.java:145)
	at io.spring.ge.conventions.gradle.WorkingDirectoryProcessOperations.exec(WorkingDirectoryProcessOperations.java:45)
	at io.spring.ge.conventions.gradle.ProcessOperationsProcessRunner.run(ProcessOperationsProcessRunner.java:41)
	at io.spring.ge.conventions.core.BuildScanConventions.run(BuildScanConventions.java:166)
	at io.spring.ge.conventions.core.BuildScanConventions.addGitMetadata(BuildScanConventions.java:113)
	at io.spring.ge.conventions.gradle.GradleConfigurableBuildScan.lambda$background$0(GradleConfigurableBuildScan.java:104)
	at com.gradle.scan.plugin.internal.api.j.a(SourceFile:22)
	at com.gradle.scan.plugin.internal.api.k$a.a(SourceFile:112)
	at com.gradle.scan.plugin.internal.api.h.a(SourceFile:62)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

然后我就进行了如下的尝试,当然结果是令人开心的,不然我也不会在这里记录了。

zhangyao@MacBookPro spring-framework-5.2.22.RELEASE % git init
zhangyao@MacBookPro spring-framework-5.2.22.RELEASE % git add .
zhangyao@MacBookPro spring-framework-5.2.22.RELEASE % git commit -m "init spring-framework-5.2.22.RELEASE"

add spring debug module for my test

再次编译整个项目,发现没有那个git的报错了!!!

java spring 调试 如何调试spring源码_gradle_12