概述

官方地址https://spring.io/projects/spring-framework
Github地址:https://github.com/spring-projects/spring-framework

源码环境搭建

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

  1. git clone git@github.com:spring-projects/spring-framework.git
  2. cd spring-framework
  3. git checkout 5.2.x

idea

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

  1. /gradlew :spring-oxm:compileTestJava
  2. > Task :spring-oxm:genJaxb
  3. [ant:javac] : warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
  4. [ant:javac] 警告: [options] 未与 -source 8 一起设置引导类路径
  5. [ant:javac] 1 个警告
  6. BUILD SUCCESSFUL in 3m 28s
  7. 40 actionable tasks: 24 executed, 16 from cache

修改build.gradle,增加

  1. maven{ url 'https://maven.aliyun.com/nexus/content/groups/public/'}
  2. maven{ url 'https://maven.aliyun.com/nexus/content/repositories/jcenter'}

image.png处理 aspect

图片.png

1. 下载Spring源码

这里有的小伙伴可能不知道源码在哪下载,没关系!这种问题的思路一般是我们要搞某个技术,第一反应就是先上它的官网。直接在浏览器搜索栏输入 Spring,就能看到它的官网了。
Spring——概述 - 图3
打开 Spring 的官网:https://spring.io/
Spring 全家桶包含的项目有很多,我们选择我们今天要搞的 Spring 框架:
Spring——概述 - 图4
这里你就可以看到最新的正式发布版本已经是 5.3.8 的,真的是更新的好快,反正咱们是学习(实际项目千万别用最新版本),这里我就带大家来编译最新的版本,这样大家也可以学习到最新的功能特性。
当然了这个版本不重要,你也可以选择其他版本,咱今天是授人以渔,不是授人以鱼,重要的是学习这个方法,你看完后想编译啥版本就编译啥版本。
Spring——概述 - 图5
我们点击右上角的 github 图标就会跳转到 github 上面的源码项目了。
Spring——概述 - 图6
下载方式可以直接通过 git clone 或者 下载 zip 包自己解压下,我这里是直接下载 zip 包了。
下载地址:https://github.com/spring-projects/spring-framework/releases
Spring——概述 - 图7

2. 阅读Spring的官方编译文档

其实呀,很多搞不定 Spring 源码编译的小伙伴,肯定很多都是去网上随便找个教程,结果各种踩坑,因为搜到的资料参差不齐,这点估计大家都深有体会了。
所以我们就要养成一个习惯,必须要看官方文档。这里也不是要求大家其它资料不看,毕竟也有很多优秀的博客,大家都是成年人,肯定是全都要喽。
官方文档一般都是英文,但是别害怕,我这个大学四级都考了三回的英语渣,都能勉强看,大家肯定都没问题了,况且咱可以借助翻译插件嘛。
如何编译 Spring 源码其实 Spring 官方提供了详细的文档,有离线版也有在线版,也就是开源项目都有的 REDAME 文件。
我这里选择离线版来演示吧。我们解压进入到下载好的 Spring 框架源码项目下,查看 REDAME 。
Spring——概述 - 图8
就会发现有一个 build from source 的章节。
Spring——概述 - 图9
点击这个链接,就会看到详细的编译构建 Spring 框架源码的文档了:https://github.com/spring-projects/spring-framework/wiki/Build-from-Source
Spring——概述 - 图10
接下来,咱们就按照文档来编译 Spring-Framework5.3.8 版本的源码。根据文档的说明,首先我们要有一个 JDk8 或者更高的版本环境,我电脑安装的是 JDk11 所以没啥问题。然后要安装 Git,用来拉取源代码的,因为我们已经下载了源代码,就不管它了。

3. 修改配置

先别着急,在编译构建之前,教大家一绝招。这也是我在编译过程中实践出来滴心得。

从本地下载gradle

因为第一次运行就会去下载 gradle 到本地,然后通过 gradle 来编译 Spring 源码。这个就很慢了,外网服务器下载,你懂得,有被墙的风险,并且本身也贼慢。
那为什么开始编译构建就会自动下载 gradle 呢?从哪里下载?下载的版本是多少?
我们打开 Spring 源码的根目录:
Spring——概述 - 图11
配置文件的地址就是源码根目录的二级目录下的 gradle-wrapper.properties 文件。
打开文件包含下列内容:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

  • distributionUrl:表示的就是 gradle 的下载地址,默认配置的是一个远程 URL。
  • distributionBase:下载后存放的目录,默认就是用户目录下的 .gradle 目录;
  • zipStoreBase:解压后存放的目录

我在构建的过程中发现配置的下载地址下载非常慢,经常超时,甚至有时候被墙。
所以我们倒不如先下载到本地,然后修改配置文件从本地获取 gradle,这样一来编译构建就会快很多了。
我们只需要修改 gradle 的下载地址就好了,其他的配置项建议保持不变。
Spring——概述 - 图12
上述配置的意思就是如果我们运行 gradlew 会自动去 file\:///Users/sevenluo/IdeaProjects/spring-simple/gradle-6.8.3-bin.zip 这个目录下载一个 gradle 到当前用户的 .gradle\wrapper\dists目录 ,然后解压到当前用户的 .gradle\wrapper\dists 目录。
但是实际目录不是这个,这个命令还会自己生成一些目录。下图是七哥电脑实际 gradle 的下载解压目录:
Spring——概述 - 图13
我本地使用的是 gradle-6.8.3-bin.zip ,如果你本地网络没问题可以自行去官网下载,当然七哥也下载好了,放到后台了,在公众号【七哥聊编程】回复:spring源码 就会都发送给你了。

修改远程仓库

改完上面的配置也先别着急运行编译,现在解决了下载 gradle 慢的问题,但是编译开始会使用 gradle 从远程仓库下载大量相关依赖的包。
如果你采用默认配置,那么我可以负责任的告诉你,你绝对得等呀等呀等,等的黄花菜都凉了。而且还有很大可能会失败!原因也是因为默认仓库是国外的服务器,速度真的是没谁了,想屎,不烦躁都不行。
所以呀,这里我们要把远程仓库改为咱们国内的阿里云,这样就舒服多了,怎么改?
很简单,找到 Spring 源码根目录下的 build.gradle,打开编辑添加阿里云的仓库。
Spring——概述 - 图14
maven { url ‘https://maven.aliyun.com/repository/public‘ } // 阿里云
maven { url ‘https://maven.aliyun.com/repository/gradle-plugin‘ } // 插件

那到这里,可以运行了?
no!no!no!,hold on, hold on

再打开 Spring 源码根目录下的 settings.gradle 文件,添加阿里云仓库。
Spring——概述 - 图15
maven { url ‘https://maven.aliyun.com/repository/public‘ } //阿里云
maven { url ‘https://maven.aliyun.com/repository/gradle-plugin‘ } //插件

至此万事具备只欠东风了,就等我们开始编译。
当然上面这些配置优化是七哥在实践中自己总结出来的,如果你的网速够快你完全可以不用优化,直接运行下面的命令。

4. 开始编译构建

我们编译构建 Spring 源码,一般都是要导入到 IDEA 里面进行测试或者阅读的。Spring 对于如何导入也提供了文档,是不是很贴心。当然也有导入 Eclipse 的文档,大家可以根据自己的需求来操作。我这里是用 IDEA 的,你如果导入 Eclipse 操作也都是基本上一样的。
导入 idea 的文档地址:https://github.com/spring-projects/spring-framework/blob/main/import-into-idea.md
Spring——概述 - 图16
根据文档的提示在导入 idea 之前需要去 Precompile spring-oxm ,也就是预编译 spring-oxm 这个项目。
./gradlew :spring-oxm:compileTestJava

执行这个命令成功后,就得到下图:
Spring——概述 - 图17
预编译起来也很快,我电脑上一共耗时 23 毫秒。
然后我们还要预编译下 spring-core 这个项目,因为后面我们运行测试模块的时候需要用到里面的类。
./gradlew :spring-core:compileTestJava

执行成功后如图:
Spring——概述 - 图18

5. 导入IDEA

  1. 开始使用idea导入Spring源码,File -> New -> Project from Existing Souces…

Spring——概述 - 图19

  1. 选择 Spring 源码项目的目录,进而选择根目录当中的 build.gradle 文件导入;

Spring——概述 - 图20

  1. 导入 idea 之后会开始自动构建、建立索引,这个过程也是很漫长,你只能等,我这边用了不到7分钟,看电脑性能;

Spring——概述 - 图21

  1. 接下来我们对 idea 进行一些设置,不然每次 idea 运行都会通过 gradle 去编译运行。gradle 运行编译特别慢,需要改成 idea 自己编译运行.

Spring——概述 - 图22
说明一下,这里不是一定要改,但是如果你不改用默认的则会特别慢,改成 idea 快的不止一点点。
到这,我们的 spring 框架源码就编译完了,为了检验我们的劳动成果,下面建一个 moudle 来测试一下。

6. 验证测试

  1. 在我们的 spring 源码项目下新建我们自己的测试module,如下图所示;

Spring——概述 - 图23
Spring——概述 - 图24
输入测试的 moudle 名:
Spring——概述 - 图25

  1. 建好项目之后往 gradle 的配置文件中添加 spring 的依赖,相当于你建了一个 maven 项目,在 pom 文件中添加 spring 的依赖;

implementation(project(“:spring-context”))

修改后的配置:
Spring——概述 - 图26

  1. 写测试代码;
  • 配置类的代码,用于指定扫描的bean;

package com.sevenluo.spring.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(“com.sevenluo.spring”)
public class AppConfig {
//扫描ccom.sevenluo.spring包下面的所有bean
}

  • 写一个sevice,被扫描的bean;

package com.sevenluo.spring.services;

import org.springframework.stereotype.Service;

@Service
public class HelloService {
public void hello() {
System.out.println(“Hello,sevenluo!”);
}
}

  • 测试类代码;

Spring——概述 - 图27

  1. 右键运行——可能你会出现一些错误;比如博主这里就出现了:

java: 程序包jdk.jfr不存在` 错误;

Spring——概述 - 图28
这个问题是因为 jdk.jfr 是 java9 以后才有的模块,而 spring 源码 5.3.8 版本已经使用这个包,所以我们需要设置我们项目配置的 jdk 版本高于9。
排查后,是因为 idea 配置的 java 编译的版本是8,改为11即可。
Spring——概述 - 图29
最后再次运行,就成功了。
Spring——概述 - 图30

参考
https://mp.weixin.qq.com/s?__biz=MzkxODI2MDMzMA==&mid=2247484026&idx=1&sn=cb7cf56b220fb0d8efc18dad92f2583c&chksm=c1b55d7ff6c2d4698edcc0cfd8873be32d9b2987ad02bb8c2c24fa1474721c96d147143980dc&scene=178&cur_album_id=1953180184375787523#rd