Spring Framework 5.3.29 源码编译 环境搭建


准备工作

  • git
    • git.exe 所在目录添加到 Path 中
  • gradle
    • 添加环境变量 GRADLE_USER_HOME, 指定到一个自定义目录, 用于存放 Gradle 的本地仓库和 Gradle Wrapper 的缓存文件
      • 默认会创建 $USER_HOME/.gradle 目录并存储这些内容
    • 添加环境变量 M2_HOME 指向 Maven 安装目录
      • Gradle 寻找 Maven 本地仓库的策略优先级如下, 确认寻找路径, 确保仓库 mavenLocal() 有效
      • USER_HOME/.m2/settings.xml >> M2_HOME/conf/settings.xml >> USER_HOME/.m2/repository
  • Idea, File | Settings | Build, Execution, Deployment | Build Tools | Gradle, 修改 Gradle user home 的值与环境变量 GRADLE_USER_HOME 的值相同
  • JDK 8 Update 60 以上即可构建 Spring 5.3.29
    • 在 Project Structure 里选择合适的 SDK 和 合适的 Language Level
    • 在 File | Settings | Build, Execution, Deployment | Build Tools | Gradle 里 Gradle JVM 选择 Project SDK
    • 选择 JDK 11 及以上, 编译时提示的警告会打断编译流程, 通常警告不应该打断才对, 不知道哪里能配置

检出代码

GtiHub Spring Framework

截至到 20230821, Spring 5 的最新正式版本是 5.3.29

通过 Git 的方式把代码从 [email protected]:spring-projects/spring-framework.git 拉下来, 文件夹名称叫 spring, 使用命令 git checkout -b 5.3.29 v5.3.29 将 Tag v5.3.29 检出为分支 5.3.29

修改根目录下 build.gradle 的内容, 在 repositories 节点中添加 Maven 本地仓库和阿里云仓库, 构建速度可能会快一点

		repositories {
			mavenLocal()
			maven {url 'https://maven.aliyun.com/repository/public'}
			mavenCentral()
			maven { url "https://repo.spring.io/libs-spring-framework-build" }
		}

导入向导

源码中自带导入 Idea 的说明文件 import-into-idea.md, 大致意思如下

  • 进入到源码根目录
  • 执行 gradlew :spring-oxm:compileTestJava 命令来预编译 spring-oxm 模块
  • 源码导入 Idea, File -> New -> Project from Existing Sources -> Navigate to directory -> Select build.gradle
  • 排除 spring-aspects 模块, File-> Project Structure -> Modules
  • 没了

预编译

在源码文件夹打开终端, 执行 gradlew :spring-oxm:compileTestJava, 会先自动从 https://services.gradle.org/distributions/gradle-x.x.x-bin.zip 下载 gradle-x.x.x-bin.zip, 和一些依赖, 如果网络不行的话, 可能会报错. 一切顺利的话, 构建成功后大概显示如下内容

在这里插入图片描述

导入 Idea

先打开一个项目, 然后点击 File -> New -> Project from Existing Sources -> 找到 build.gradle 文件, 点击 OK, Idea 会自动开始 Gradle Build, 会下载很多依赖, 等待其完成. 一切顺利的话, 构建成功后大概显示如下内容

Starting Gradle Daemon...
Gradle Daemon started in 2 s 357 ms
> Task :buildSrc:compileJava UP-TO-DATE
> Task :buildSrc:compileGroovy NO-SOURCE
> Task :buildSrc:pluginDescriptors UP-TO-DATE
> Task :buildSrc:processResources UP-TO-DATE
> Task :buildSrc:classes UP-TO-DATE
> Task :buildSrc:jar UP-TO-DATE
> Task :buildSrc:assemble UP-TO-DATE
> Task :buildSrc:pluginUnderTestMetadata UP-TO-DATE
> Task :buildSrc:compileTestJava NO-SOURCE
> Task :buildSrc:compileTestGroovy NO-SOURCE
> Task :buildSrc:processTestResources NO-SOURCE
> Task :buildSrc:testClasses UP-TO-DATE
> Task :buildSrc:test NO-SOURCE
> Task :buildSrc:validatePlugins UP-TO-DATE
> Task :buildSrc:check UP-TO-DATE
> Task :buildSrc:build UP-TO-DATE
> Task :prepareKotlinBuildScriptModel UP-TO-DATE

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See https://docs.gradle.org/7.5.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 34s
6 actionable tasks: 6 up-to-date

A build scan was not published as you have not authenticated with server 'ge.spring.io'.
For more information, please see https://gradle.com/help/gradle-authenticating-with-gradle-enterprise.
> Task :prepareKotlinBuildScriptModel UP-TO-DATE

BUILD SUCCESSFUL in 1s

如果出现什么问题, 可以像刷新 Maven 一样去重新载入 Gradle 项目, 在 Build 这个工具窗体中查看构建输出内容

构建完成之后, 点击 File - Project Structure - Modules, 移除子模块 spring-aspects

新建模块

点击项目, 新建一个 Gradle 模块, 用于测试和 debug

在这里插入图片描述

Idea 会自动创建一个 Main 类, 点击运行会自动开启 Gradle 构建, 之后会成功运行, 输出 Hello World!

package com.coder;

public class Main {
    
    
	public static void main(String[] args) {
    
    
		System.out.println("Hello world!");
	}
}

为了使用 Spring 的相关功能, 需要在该模块中 build.gradle / build.gradle.kts 的 dependencies 中添加 spring-context 的引用 implementation(project(":spring-context")), 然后刷新 Gradle 配置

添加如下配置类, 点击运行会自动开启 Gradle 构建, 之后会成功运行, 输出 demo, 说明 Spring 的功能引入正常

@Configuration
public class Application {
    
    

	@Bean
	public String string() {
    
    
		return "demo";
	}

	public static void main(String[] args) {
    
    
		AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Application.class);
		Object bean = ac.getBean("string");
		System.out.println(bean);
	}

}

至此, import-into-idea.md 说明中的操作全部成功, 可以愉快地开启 Spring 源码之旅了

只是有一点很不爽, 每次运行自己的代码, 都得先执行一大堆 Gradle 自带的 Task, 顺利的时候需要几秒钟, 不顺利时可能就得几十秒, 有点影响心情

问题说明

如果 Gradle 编译报错时, 控制台的中文显示为 ������, 则可以点击 Help - Edit Custom VM Options…, 添加 -Dfile.encoding=UTF-8, 然后重启 Idea

在这里插入图片描述

IDEA 使用 gradle 乱码之谜

期间可能会出现如下的错误, 从最后一层的结果可能看不出来是什么原因, 可以往上看一下(绿框), 问题可能就很明显的展示出来了

在这里插入图片描述
在这里插入图片描述

Gradle Tasks

默认情况下, Idea 的 Gradle 项目会使用 Gradle 来构建项目和运行任务. 这样在构建和运行我们自己的模块时, 总是得先等待 Gradle 的一堆任务执行完毕, 才能轮到我们的自己的代码, Gradle 的任务通常要耗时几秒钟, 偶尔会长点, 十几二十几秒的样子

可通过如下办法能跳过 Gradle 的一堆任务, 直接构建和运行我们自己创建的模块

点击 File - Settings - Build, Execution, Deployment - Build Tools - Gradle, Build and run usingRun tests using 两个选项都选择 IntelliJ IDEA

设置了上述选项后, 构建和运行代码会出现一大堆各种各样奇奇怪怪的问题, 这些问题有的好解决, 有的则很麻烦. 在网上找, 不一定找得到, 也不一定管用, 不清不楚的不说, 还会把项目搞得一团糟

如果能接受每次构建和运行自己的代码时, 先跑一堆 Gradle 的任务, 大概几秒钟, 那就可以不用设置该选项, 也不需要解决各种问题. 我个人是妥协了, 反正 Gradle 的任务也花不了几秒钟

另外, 使用 IntelliJ IDEA 的方式构建, 需要下载一些依赖到 USER_HOME/.m2, 下载过程可以在 Build 工具窗体中看到, 其中有两个 Jar 包很大, 下载超慢, 可以到 Maven 仓库 搜索并下载(迅雷下载很快), 然后扔到 .m2 目录对应文件夹下, 然后重启 Idea, 重新构建即可

下面是直接使用 IntelliJ IDEA 构建时报的几个错, 我并没有去解决全部的这些问题. 使用 Gradle 构建的话则不会出现这些问题

1

C:\mrathena\develop\workspace\idea\mrathena\spring\spring-core\src\main\java\org\springframework\core\metrics\jfr\FlightRecorderStartupEvent.java:19:15
java: 程序包jdk.jfr不存在

网上找了半天, 都说是在 Settings - Gradle 中把 Gradle VM 的版本改成 JDK 11, 然而对我来说不管用. 找了好久才发现一篇文章说, 需要把 Java Compiler 的版本改成 11, 我试过后, 确实是有效的. 可见, 就算问题看似相同, 实际的原因却不一定相同, 也有可能是别人误打误撞的解决了而已, 论问题原因和解决原理, 肯定是不清不楚的

2

C:\mrathena\develop\workspace\idea\mrathena\spring\spring-context\src\main\java\org\springframework\context\weaving\DefaultContextLoadTimeWeaver.java:26:38
java: 找不到符号
  符号:InstrumentationSavingAgent
  位置: 程序包 org.springframework.instrument

3

因为我已经决定不配置 Gradle 的 Build and Run 了, 所以就没有再继续, 不过我以前解决过一次 Spring 5.2.13 的源码问题, 可以看一下

Spring 5.2.13 源码编译 环境搭建

提交代码

学习源码一定会在源码中做自己的注释, 需要把源码托管到自己的 Git 仓库

在代码托管平台创建一个项目如 spring-source-5.3.29, 拿到对应仓库链接

将源码根目录下 .git\config 打开, 修改 remote 下的 url 为该仓库地址并保存

执行提交与推送的命令, 将源码推送至远程仓库即可

猜你喜欢

转载自blog.csdn.net/mrathena/article/details/132412678