1. 程式人生 > 其它 >詳細圖文一步步記錄Spring 5.3原始碼編譯和除錯(IDEA+Gradle)的過程

詳細圖文一步步記錄Spring 5.3原始碼編譯和除錯(IDEA+Gradle)的過程

1 前言

最近稍微研究了一下spring原始碼,看了不少資料發現不少大佬都是將spring原始碼拉到本地,自己編譯完成之後在原始碼裡面直接寫註釋,當然也更方便了自己學習和除錯。所以我也做了一次嘗試,在此記錄一下編譯的過程和遇到的問題。

2 環境準備

本地編譯spring原始碼我使用的個軟體版本如下:

  • 系統:Mac os Big Sur
  • IDEA:2020.1.2
  • gradle6.8.3
  • spring5.3.7-SNAPSHOT
  • jdk11.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 修改配置

下面我們需要逐步解釋/修改一下上圖紅框中的檔案:

  1. import-into-idea.md
    這是官方提供的spring原始碼匯入idea的步驟和注意說明,這裡我就不去翻譯了,只需要跟著後續的步驟操作就行。當然感興趣的話可以點選文章閱讀一下人家已經翻譯完成的。
  2. 修改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
  1. 修改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中寫到的要求,我們需要先進行兩次預編譯。

  1. 預編譯spring-oxm
$ ./gradlew :spring-oxm:compileTestJava

構建截圖如下:

2. 預編譯spring-core

$ ./gradlew :spring-core:compileTestJava

構建截圖如下:

3.4.2 匯入IDEA

完成預編譯之後我們就終於可以把spring原始碼匯入IDEA了~~

  1. 首先需要在idea中為新專案配置一下gradle的本地倉庫目錄,如果不配置的話,當你匯入的時候idea會自動把依賴包下載到gradle預設目錄下。

  2. 開始匯入專案

    選擇我們的spring原始碼專案,使用gradle編譯

    點選finish,idea就會開始自動編譯spring專案,此過程中還會去下載專案的依賴(jar包)。

    等待過程中再去設定裡面修改一下gradle軟體的地址:

    看到BUILD SUCCESSFUL我們的spring原始碼專案就已經編譯成功了!!

4 驗證

看到這裡,恭喜你,spring原始碼的編譯終於成功了!接下來我們進行一下簡單的驗證。

  1. 在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 問題

最後再主要說一下在編譯過程中我遇到的一些問題。

  1. 錯誤: 程式包jdk.jfr不存在
    這是jdk的版本不對,換成jdk11就不會出現這種問題,這就是為什麼3.3節中需要把java的版本改成jdk11。
  2. 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