聽說你還沒學Spring就被原始碼編譯勸退了?30+張圖帶你玩轉Spring編譯

程式設計師DMZ發表於2020-07-03

原始碼學習第一步,Spring原始碼編譯

之所以寫這麼一篇文章是因為群裡的小夥伴在編譯原始碼時碰到了問題,再加上筆者自身正準備做一個原始碼的註釋版本,恰好也需要重新編譯一份程式碼,至於為什麼要將原始碼編譯到本地就不用多說了吧?

比如,你可以任意的新增註釋,一邊讀原始碼一邊記筆記,甚至你可以修改原始碼,更好的除錯程式等等。但是如果你堅持通過匯入依賴或者引入jar包的方式來學習原始碼,我覺得也可以,沒有最好的,只有最適合自己的!

本文的主要目的是幫助那些在原始碼學習之初就被原始碼編譯勸退的同學重拾信心!

話不多說,我們開始正題

參考官方文件:

https://github.com/spring-projects/spring-framework/wiki/Build-from-Source

https://github.com/spring-projects/spring-framework/blob/master/import-into-idea.md

前期準備

  1. 確保本機已經安裝好了git
  2. jdk對應版本為1.8

Snipaste_2020-07-03_10-22-10

  1. Gradle,目前不需要安裝,在編譯的時候根據原始碼提示按照對應版本的Gradle即可
  2. IDEA,我使用的版本如下:

image-20200703162142721

1、獲取Spring原始碼

這裡我推薦使用clone的方式將原始碼拉取到本地,最大的好處在於可以利用IDEA直接比較版本間的差異,例如

在這裡插入圖片描述

在上圖中我本地編譯的5.0版本的程式碼,所以我對比的是5.05.1版本populateBean方法實現的差異。

接下來我們開始拉取Spring原始碼,大家可以按照以下幾步進行

  1. 在任意磁碟路徑下新建一個資料夾,名稱隨便取,建議為SpringFramWork
  2. 進入SpringFramWork資料夾中,開啟git命令列,輸入以下命令
git clone https://github.com/spring-projects/spring-framework.git

接著等待倉庫克隆完畢,這個過程可能會耗費比較長的時間,如果實在不行的話,大家可以直接將原始碼的壓縮包down下來。

clone666

如果你是跟我一樣直接拉取的程式碼,記得切換到5.2.x版本,在命令列中執行命令:

 git checkout origin/5.2.x

2、新增阿里雲映象

在編譯過程中,Spring會去自動下載一些依賴的包,預設使用的是官方的映象,下載比較慢,所以我們提前新增好國內映象,將下面這行程式碼貼上到build.gradle檔案中的repositories節點下即可 ,

//新增阿里雲映象
maven { url "http://maven.aliyun.com/nexus/content/groups/public" }

如下圖所示在這裡插入圖片描述

3、預先編譯spring-oxm模組

開啟命令列視窗,並切換到原始碼所在資料夾,執行以下命令

gradlew :spring-oxm:compileTestJava

出現BUILD SUCCESS字樣時說明構建成功,如下圖所示

bulid

4、根據編譯後的原始碼下載並安裝對應的版本的Gradle

在完成對spring-oxm模組的編譯後,會在當前目錄生成一個.gradle資料夾,開啟後可以檢視對應的Gradle版本。

Snipaste_2020-07-03_15-11-3

雙擊開啟.gradle資料夾就能看到對應所需要的gradle的版本號

Snipaste_2020-07-03_15-15-

大家直接在這個網站上下載對應所需要的版本即可:https://gradle.org/releases/,選擇 binary-only

安裝好後記得配置Gradle的環境變數

  • 新增 GRADLE_HOME 環境變數,指向Gradle解壓目錄
  • 配置Path環境變數:新增 %GRADLE_HOME%\bin

之後測試是否安裝成,在命令列中輸入以下命令:gradle -v,檢視是否正確輸出了對應版本。

image-20200703152417552

5、為安裝好的Gradle配置國內映象

進入Gradle安裝目錄,在init.d目錄下新建一個init.gradle檔案,並新增以下內容:

allprojects{
    repositories {
        def REPOSITORY_URL = 'http://maven.aliyun.com/nexus/content/groups/public/'
        all { ArtifactRepository repo ->
            def url = repo.url.toString()
            if ((repo instanceof MavenArtifactRepository) && (url.startsWith('https://repo1.maven.org/maven2') || url.startsWith('https://jcenter.bintray.com'))) {
                project.logger.lifecycle 'Repository ${repo.url} replaced by $REPOSITORY_URL .'
                remove repo
            }
        }
        maven {
            url REPOSITORY_URL
        }
    }
}

如下圖所示:

gradle-init

6、將程式碼匯入到IDEA中

6.1、開啟IDEA並選擇匯入專案

image-20200703154502944

6.2、選擇匯入一個Gradle專案

image-20200703154634013

6.3、配置匯入的專案

image-20200703154919932

點選Finish後等待IDEA構建完專案,如果你之前已經按照我的方法配置了Gradle的國內映象,這個過程不會太久,我們本機只用了10多分鐘就構建完成了

構建完成後整個專案結構如下:

image-20200703155239583

如果你跟我一樣是直接檢出的程式碼,記得將分支切換到5.2.x

source-checkout

7、構建整個專案

選擇Build > Build Project

image-20200703162734719

可能出現的問題

AnnotationCacheAspect找不到符號

在這個過程中你可能會碰到如下錯誤:

20190328102605453

這是因為AnnotationCacheAspect.aj 不是java檔案需要另外的aspectj 進行處理,可以按照以下步驟解決這個問題

開啟命令列,cd到AspectJ的jar包所在的資料夾,執行java -jar aspectj-1.9.4.jar命令,開啟AspectJ的安裝介面,直接點選Next,如下圖:

image-20200703164636898

接著選擇jdk的安裝路徑,繼續Next。

image-20200703164719216

接著選擇AspectJ的安裝路徑,然後Install安裝。

img

  • IDEA中配置aspectj

確保以下兩個外掛已經被啟用

  1. Spring AOP/@AspectJ

  2. AspectJ Support

image-20200703165117938

將編譯器改為 Ajc,接著設定Ajc的安裝目錄,選擇到aspectjtools.jar,同時,一定要將Delegate to Javac選項打鉤,這個代理設定的作用只對指定的專案進行Ajc編譯,其他的專案還是用預設的javac編譯器編譯。如果不勾選這個代理選項,則全部專案都使用Ajc編譯器編譯,可能會導致編譯錯誤。

image-20200703165837296

  • 指定需要使用Ajc編譯的專案

分別為spring-aopspring-aspects新增Facets屬性。

點選File --> Project Structure --> Facets,選擇spring-aop.main,點選OK

點選File --> Project Structure --> Facets,選擇spring-aspects.main,點選OK

完成新增,如下圖所示:

在這裡插入圖片描述

完成上述步驟後,再次選擇Build > Build Project ,成功完成編譯

8、新增測試模組

8.1、右鍵工程名 ---> new ---> module

image-20200703172538821

8.2、選擇Gradle及Java

image-20200703172305000

8.3、輸入模組名稱

image-20200703172720394

點選next ---> Finish 完成測試模組的建立

最後,新增一些必要的依賴,修改建立好的模組中的build.gradle檔案,新增如下三個依賴

compile(project(":spring-aop"))
compile(project(":spring-context"))
optional("org.aspectj:aspectjweaver")

如下圖所示:

在這裡插入圖片描述

至此,我們就完成了整個Spring的編譯,並且在建立了一個日後學習使用的模組!

如果本文對你有幫助的話,記得點個贊吧!也歡迎關注我的公眾號,微信搜尋:程式設計師DMZ,或者掃描下方二維碼,跟著我一起認認真真學Java,踏踏實實做一個coder。

公眾號

相關文章