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
上clone,操作步驟跟上述一致。下載完成之后如下圖所示。
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