前沿:Spring系列生態十分豐富,涉及到各個方面。但是作為Spring生態的核心基礎Spring,是最重要的環節,需要理解Spring的設計原理,我們需要解讀源碼。
在構建Spring源碼閱讀環境時,遇到一些問題。通過多次嘗試,慢慢找到了正確的構建編譯方式,下面就記錄下 Spring源碼閱讀環境的構建編譯完整過程 。【在網上也找到過許多類似的文章,但發現都不是很完整,而且講述得也不是很清晰】
最后提供構建好的源碼下載,可以直接使用!!!!!
1.搭建構建前環境
-
JDK
安裝JDK就不用介紹了,保證是jdk1.8以上的版本就行了。
-
Gradle
直接在官網下載gradle>構建工具,解壓到本地后配置環境變量。增加系統變量GRADLE_HOME=gradle的路徑,增加path= %GRADLE_HOME%\bin
-
idea工具
使用IntelliJ IDEA 2018.3.2開發工具,下載安裝激活教程。idea安裝教程
2.下載源碼
直接去github下載源碼,選擇5.x版本
https://github.com/spring-projects/spring-framework
https://repo.spring.io/libs-release-local/org/springframework/spring/
將下載的源碼解壓到本地就行,下一步就是開始構建源碼了。
3.開始構建
在cmd中進入源碼目錄,輸入gradlew.bat命令
使用工具編譯時,可能會出現內存溢出情況,這里我們編譯時需要增加相關參數
xml -XX:MaxPermSize=2048m -Xmx2048m -XX:MaxHeapSize=2048m
使用國內的地址能明顯提高依賴的下載速度
maven { url "http://maven.aliyun.com/nexus/content/groups/public/"}
發現構建gradle不通過
解決方法:關於這個問題我在網上找了很多資料,最后發現多更新幾次就沒問題了,主要是需要下載很多依賴包,但可能由於網速的問題導致失敗。總之fail了你就多refresh幾次,這個過程需要一定時間的。
等待一定時間后,構建成功!【並沒有網上說的那么難,以前的版本可能需要配置很多文件。現在的版本構建很簡單,需要失敗可能是由下載依賴包失敗導致的】
在IDEA中,如果能找到ApplicationContext類,按下Ctrl+Shift+Alt+U鍵,出現下圖所示類圖界面說明構建成功了!
此時可以查看Spring的源碼了,但是我們需要在源碼的基礎上面進行修改,開發,最好將源碼進行編譯打包,下面就是將源碼編譯的過程。
4.編譯源碼
在構建完成源碼之后,就搭建好了閱讀源碼的環境了。但是我們還可以將源碼編譯打包。在編譯之前需要進行一些配置修改,可以查看import-into-idea.md文檔
在編譯之前還需要對dosc.gradle文檔進行修改,因為有些注釋,文件路徑在編譯時需要調整。
下面將兩個地方的路勁替換使用windows環境下的反斜扛 \
- 下面給出task schemaZip中修改的部分
- it.path.endsWith(“META-INF\spring.schemas”)
- it.path.endsWith(schemas.get(key).replaceAll(’\\/’,’\\\\’))
也可以用下面的方法判斷是在什么環境中編譯,直接粘貼復制。
task schemaZip(type: Zip) {
group = "Distribution"
baseName = "spring-framework"
classifier = "schema"
description = "Builds -${classifier} archive containing all " +
"XSDs for deployment at http://springframework.org/schema."
duplicatesStrategy 'exclude'
//當前系統是否是windows的標志
def isWindows = System.properties['os.name'].toUpperCase().contains('WINDOWS')
//不同的操作系統,表示子目錄的符號是不同的
def schemaPath = isWindows ? "META-INF\\spring.schemas" : "META-INF/spring.schemas"
moduleProjects.each { subproject ->
def Properties schemas = new Properties();
subproject.sourceSets.main.resources.find {
it.path.endsWith(schemaPath)
}?.withInputStream { schemas.load(it) }
for (def key : schemas.keySet()) {
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
assert shortName != key
File xsdFile = subproject.sourceSets.main.resources.find {
//如果是windows環境,就要對路徑中的分隔符做替換
isWindows ? it.path.endsWith(schemas.get(key).replaceAll('\\/','\\\\')) : it.path.endsWith(schemas.get(key))
}
assert xsdFile != null
into (shortName) {
from xsdFile.path
}
}
}
}
接下來先編譯1. Precompile spring-oxm
with ./gradlew :spring-oxm:compileTestJava
在Precompile spring-oxm
with ./gradlew :spring-oxm:compileTestJava
編譯完成后,可以編譯整個工程了!(這個過程非常耗時間,可能20幾分鍾!)
進過一段時間編譯build成功!(每個人電腦的性能不一樣,所需時間也不一樣。 )
發現spring-aspects模塊有錯誤, 選中該模塊,右鍵–Load/Unload Modules ,把spring-aspects下的所有項目排除出去。
到這里,整個Spring源碼的編譯和環境准備就完成了,接下來我們編寫一個demo來調試一下,看看我們的代碼是否沒問題。
4.測試
完成了上面的過程后,我們可以自己編寫一個模塊測試該源碼構建編譯過程是否完成!
- 在Spring中添加自己的module模塊,同樣選擇gradle構建。
- 輸入ArtufactId,工程名
- 選擇默認的存儲路徑即可
- 確認,idea會自動幫助我們構建spring-mytest模塊。
- 下面編寫一個簡單的applicationContext獲取容器用的bean,主要是測試Spring源碼構建編譯過程是否成功!
新建User.java
package com.gqz.springtest;
/** * @ClassName: User * @author: ganquanzhong * @date: 2019/9/2 11:27 */
public class User {
private int uid;
private String username;
private String pwd;
private String tel;
private String addr;
public User(int uid, String username, String pwd, String tel, String addr) {
this.uid = uid;
this.username = username;
this.pwd = pwd;
this.tel = tel;
this.addr = addr;
}
@Override
public String toString() {
return "User{" +
"uid=" + uid +
", username='" + username + '\'' +
", pwd='" + pwd + '\'' +
", tel='" + tel + '\'' +
", addr='" + addr + '\'' +
'}';
}
}
新建JavaConfig.java (使用注解的方式聲明bean)
package com.gqz.springtest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/** * @ClassName: JavaConfig * @author: ganquanzhong * @date: 2019/9/2 11:43 */
@Configuration
@ComponentScan
public class JavaConfig {
@Bean
public User user(){
return new User(101,"ganquanzhong","pwd","13995978321","china");
}
}
最后寫一個測試類Main.java
package com.gqz.springtest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/** * @ClassName: Main * @author: ganquanzhong * @date: 2019/9/2 12:29 */
public class Main {
public static void main(String[] args){
ApplicationContext ac =new AnnotationConfigApplicationContext(JavaConfig.class);
User user = (User) ac.getBean("user");
System.out.println(user.toString());
}
}
- 運行
consoloe輸出
User{uid=101, username='ganquanzhong', pwd='pwd', tel='13995978321', addr='china'}
4.遇到的問題解決方法
這個總結下構建源碼閱讀環境過程中會遇到的問題和解決辦法。
- 在idea中導入spring5源碼構建時,spring-core模塊報錯,缺失cglib相關的jar包依賴。
為了避免第三方class的沖突,Spring把最新的cglib和obj巳nesis給重新打包(repack)了,它並沒有在源碼里提供這部分的代碼,而是直接將其放在jar包當中,這也就導致了我們拉取代碼后出現編譯錯誤。那么為了畫過編譯,我們要把缺失的jar補回來
- Aspecu編譯問題解決,主要是aspect關鍵字Java語法違背,需要使用ajc編譯器執行。下面就切換ajc編譯器,首先需要下載aspectj,並且安裝。
- 為spring-aspect工程添加Facets屬性
- 編譯器要改為Ajc,同時要設置Ajc的安裝目錄,如圖1-27所示。記住,要選擇到a spec飛jtools.jar這個層面,同時,務必要邊擇Delegateto Javac選頃,它的作用是只編譯AspectJ的Facets項目,而其他則使用JDK代理。如果不勾選,則全部使用Ajc編譯,那么會導致編譯錯誤。
-
在idea中導入spring5源碼構建時,spring-oxm模塊報錯,在gradle中找到spring-oxm的genCastor、genJaxb 命令。
經過上面的jar修復操作后,在依賴library中應該有以下幾個模塊!!!! -
build finish
源碼下載
附上我構建好的源碼,並且會一直更新源碼的分析過程,感興趣的可以start下
在README有詳細的步驟,請查看!!!!!!