詳細圖文一步步記錄Spring 5.3原始碼編譯和除錯(IDEA+Gradle)的過程
1 前言
最近稍微研究了一下spring
原始碼,看了不少資料發現不少大佬都是將spring
原始碼拉到本地,自己編譯完成之後在原始碼裡面直接寫註釋,當然也更方便了自己學習和除錯。所以我也做了一次嘗試,在此記錄一下編譯的過程和遇到的問題。
2 環境準備
本地編譯spring
原始碼我使用的個軟體版本如下:
- 系統:Mac os Big Sur
- IDEA:2020.1.2
gradle
:6.8.3
spring
:5.3.7-SNAPSHOT
jdk
:11.0.11
3 Spring編譯流程
3.1 下載安裝gradle
可以去gradle
官網下載所需版本的二進位制包,我們選擇gradle-6.8.3
即可。
下載解壓完成之後配置一下環境變數就行。配置完環境變數執行gradle -v
有需要的話我們還可以配置一下
gradle
本地倉庫的目錄(相當於maven的repo),新建一個環境變數GRADLE_USER_HOME
指定你本地的gradle
倉庫地址。下圖是我在Mac上的配置:當然這一步不做也行,
gradle
預設的本地倉庫地址是~/.gradle
,至此gradle
的安裝就完成了。
3.2 spring原始碼下載
在github上搜索spring framework
的官方原始碼:
這裡要重點說一下,我們下載原始碼的時候用git clone
命令拉取程式碼,不要直接下載它的zip包,否則後續的編譯會出現報錯!!!,具體錯誤在本文第五節會講到。
在拉程式碼之前最好把專案fork到我們自己的倉庫
如果大家覺得在github上拉程式碼速度太慢,也可以從gitee
3.3 修改配置
下面我們需要逐步解釋/修改一下上圖紅框中的檔案:
- import-into-idea.md
這是官方提供的spring原始碼匯入idea的步驟和注意說明,這裡我就不去翻譯了,只需要跟著後續的步驟操作就行。當然感興趣的話可以點選文章閱讀一下人家已經翻譯完成的。 - 修改settings.gradle檔案,加上我們國內的阿里雲maven倉庫。
maven { url "https://maven.aliyun.com/repository/public" }
修改完成後如下圖:
3. 修改gradle.properties檔案
version=5.3.7-SNAPSHOT
org.gradle.jvmargs=-Xmx2048M
org.gradle.caching=true
org.gradle.parallel=true
kotlin.stdlib.default.dependency=false
## 啟用新的孵化模式
org.gradle.configureondemand=true
## 開啟守護程序 通過開啟守護程序,下一次構建的時候,將會連線這個守護程序進行構建,而不是重新fork一個gradle構建程序
org.gradle.daemon=true
## 這個配置是指定我們的jdk目錄,其實我本地環境變數配置的是jdk1.8
## 至於這裡為什麼要重新指定為jdk11,在文章第五節會解答
org.gradle.java.home=/Users/Shared/software/jdk-11.0.11.jdk/Contents/Home
- 修改build.gradle檔案,加上使用阿里雲倉庫,提高下載速度。
maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter'}
修改完成之後如下圖:
3.4 開始構建
3.4.1 預編譯
根據import-into-idea.md中寫到的要求,我們需要先進行兩次預編譯。
- 預編譯
spring-oxm
$ ./gradlew :spring-oxm:compileTestJava
構建截圖如下:
2. 預編譯spring-core
$ ./gradlew :spring-core:compileTestJava
構建截圖如下:
3.4.2 匯入IDEA
完成預編譯之後我們就終於可以把spring
原始碼匯入IDEA了~~
- 首先需要在idea中為新專案配置一下gradle的本地倉庫目錄,如果不配置的話,當你匯入的時候idea會自動把依賴包下載到gradle預設目錄下。
- 開始匯入專案
選擇我們的spring原始碼專案,使用gradle編譯
點選finish,idea就會開始自動編譯spring專案,此過程中還會去下載專案的依賴(jar包)。
等待過程中再去設定裡面修改一下gradle軟體的地址:
看到BUILD SUCCESSFUL
我們的spring原始碼專案就已經編譯成功了!!
4 驗證
看到這裡,恭喜你,spring原始碼的編譯終於成功了!接下來我們進行一下簡單的驗證。
- 在spring原始碼專案中新建個module
選擇gradle編譯
和maven新建module一樣,指定座標
點選finish
修改build.gradle
檔案
plugins {
id 'java'
}
group 'org.springframework'
version '5.3.7-SNAPSHOT'
repositories {
mavenLocal()
maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter'}
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
implementation(project(":spring-context"))
}
編譯專案直到控制檯出現BUILD SUCCESSFUL
。
2. 寫程式碼
AService.java
的程式碼:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AService {
public void printA() {
System.out.println("A");
}
}
Main
程式碼:
import com.spring.demo.service.AService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.spring.demo.service");
AService aService = context.getBean(AService.class);
aService.printA();
}
}
直接執行main方法
大功告成!!
5 問題
最後再主要說一下在編譯過程中我遇到的一些問題。
- 錯誤: 程式包jdk.jfr不存在
這是jdk的版本不對,換成jdk11就不會出現這種問題,這就是為什麼3.3節
中需要把java的版本改成jdk11。 - git的問題
具體報錯資訊:
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:417)
at org.gradle.process.internal.DefaultExecAction.execute(DefaultExecAction.java:38)
at org.gradle.process.internal.DefaultExecActionFactory.exec(DefaultExecActionFactory.java:152)
at io.spring.ge.BuildScanConventions.exec(BuildScanConventions.java:162)
at io.spring.ge.BuildScanConventions.addGitMetadata(BuildScanConventions.java:111)
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:61)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
如果spring原始碼包下載的是zip包,那就有可能出現這種問題,用git clone拉取原始碼這種問題便會解決。
3. 預編譯成功,但在idea裡面會出現testCompiler()不存在
具體報錯資訊:
Could not find method testCompile() for arguments [{xxx] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
這可能是你本地下載的gradle版本是7.0+,建議將gradle版本換成6.x,問題解決。
參考文章:https://www.cnblogs.com/mazhichu/p/13163979.html