一. 前言

Spring Boot 3 RELEASE版本于 2022年11月24日 正式发布,相信已经有不少同学开始准备新版本的学习了,不过目前还不建议在实际项目中做升级,毕竟还有很多框架和中间件没出适配版本。此次Spring Boot里程碑的升级也要求了最低JDK 17Spring Framework 6 ,其核心框架的 Spring 也在 2022年11月16日 迎来了从 5.3.x6.0.x 重大版本升级,借着这个机会,写一篇关于 Spring 6 源码编译和如何高效阅读 Spring 源码的教程。

二. 环境声明

Spring源码编译官方文档:https://github.com/spring-projects/spring-framework/wiki/Build-from-Source

根据官方文档描述, Spring 6 需要 JDK 17

基础环境 版本 本地路径
操作系统 Windows 11 -
Spring源码 6.0.2 D:\SourceCode\spring-framework
Java环境 JDK 17 D:\Java\jdk-17.0.3.1
编译工具 Gradle 7.6 D:\softs\gradle-7.6
开发工具 IDEA 2022.2.3 -

三. JDK 安装

1. 下载JDK17

下载链接: https://download.oracle.com/java/17/latest/jdk-17_windows-x64_bin.exe

下载后静默安装即可,按需修改 JDK 路径(D:\Java\jdk-17.0.3.1)

2. 配置环境变量(可忽略)

配置环境 JDK 环境变量非必须!考虑到大多数人因为老项目JAVA_HOME配置JDK8的情况,下文是通过设置 Gradle 指定 JDK 版本方式。

添加系统变量 JAVA_HOME = D:\Java\jdk-17.0.3.1

添加Path:%JAVA_HOME%\bin

验证:java -version

四. Gradle 安装

1. 下载Gradle

下载地址:https://gradle.org/releases

下载解压到指定目录(D:\softs\gradle-7.6)

2. 配置环境变量

添加系统变量:GRADLE_HOME=D:\softs\gradle-7.6

添加至Path路径(%GRADLE_HOME%\bin)

查看版本 gradle -v

3. 配置镜像仓库

在gradle安装位置(D:\softs\gradle-7.6\init.d) 目录下新建 init.gradle 文件

参考阿里云官方gradle配置指南:https://developer.aliyun.com/mvn/guide ,init.gradle 完整内容如下

allprojects {
repositories {
maven { url 'file:///D:/data/.m2/repository'} // 本地仓库地址,如果没有依次向下寻找
maven { url "https://maven.aliyun.com/repository/public" }
mavenLocal()
mavenCentral()
}
buildscript {
repositories {
maven { url 'https://maven.aliyun.com/repository/public' }
mavenLocal()
mavenCentral()
}
}
}

五. 源码编译

1. 获取Spring源码

不建议zip包方式下载源代码,具体看官方issue:https://github.com/spring-projects/spring-framework/issues/24467

IDEA 选择 File → New → Project from Version Control 输入Spring源码仓库地址:

地址 备注
Github https://github.com/spring-projects/spring-framework.git 速度慢
GitCode https://gitcode.net/mirrors/spring-projects/spring-framework.git 国内镜像,速度极快

IDEA源码获取完成之后,因为当前时间最新稳定版tag是v6.0.2版本 ,所以还需要进行分支切换:

git checkout -b v6.0.2
git pull origin v6.0.2

2. 环境设置

  • IDEA设置

    File → Settings → Build,Execution,Deployment → Build Tools → Gradle

  • build.gradle

    找到 repositories 配置节点,新增阿里云镜像仓库地址

    maven { url "https://maven.aliyun.com/repository/public" } // 阿里云镜像仓库

  • settings.gradle

    找到 repositories 配置节点,新增阿里云镜像仓库地址

    maven { url "https://maven.aliyun.com/repository/public" } // 阿里云镜像仓库

  • gradle.properties

    项目内 gradle.properties 配置文件添加java路径

    org.gradle.java.home=D:\Java\jdk-17.0.3.1

3. 编译步骤

在完成上述的源码导入和相关设置之后,就可以进行源码编译了。

参考IDEA导入说明文档 import-into-idea.md ,仅需三步:

  1. Precompile spring-oxm with ./gradlew :spring-oxm:compileTestJava

    Windows 环境 CMD 输入 gradlew :spring-oxm:compileTestJava 先执行 spring-oxm 的预编译

  2. Import into IntelliJ (File -> New -> Project from Existing Sources -> Navigate to directory -> Select build.gradle)

    File → New → Project from Existing Sources → Select File or Directory to import 选择 build.gradle 点击 OK 完成编译

  3. When prompted exclude the spring-aspects module (or after the import via File-> Project Structure -> Modules)

六. 测试案例

在完成上文 Spring 源码编译之后,Congratulations ! 接下来新增一个示例模块来依赖工程中的其它 spring 模块做个简单的测试。

1. 新增模块

File → Module 新增 spring-sample 示例模块

2. 添加依赖

spring-sample 模块下的 build.gradle 新增 spring-context 依赖,它是包含了 spring-corespring-bean 和 IoC容器等Spring 运行时上下文的依赖。

 api(project(":spring-context"))

3. 测试代码

代码结构

/**
 * 人接口
 */
public interface IPersonService {  /**
  * 说
  */
 void speak(); }
/**
 * 中国人
 */
@Service
@Primary
public class ChineseService implements IPersonService {
 @Override
 public void speak() {
  System.out.println("我会说中文");
 }
}
/**
 * 美国人
 */
@Service
public class AmericanService implements IPersonService {
 @Override
 public void speak() {
  System.out.println("I can speak English");
 }
}
/**
 * 启动测试类
 */
@ComponentScan("com.youlai.spring.sample.**")
public class SpringSampleApplication {  public static void main(String[] args) {
  AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
    SpringSampleApplication.class
  );   IPersonService personService = context.getBean(IPersonService.class);
  personService.speak();
 }
}

4. 测试结果

image-20221210232239371

七. 源码阅读

本章节就基于编译好的 Spring 源码环境进行源码调试,为了方便下面就基于上章节的测试案例来对 getBean 源码流程分析,后续会更新出 Spring 源码阅读系列文章。

1. getBean 源码

  • 快速定位: 通过 Debug (F7)可以很清晰看到详细的调用栈

image-20221210230131704

getBean时序图

  • 深入概念原理

    时序图反映了在getBean()调用链中 DefaultListableBeanFactory 承担着核心角色,甚至可以说是 Spring 最核心的一个 BeanFacory 实现 ,也被称为 Spring 的 “发动机”,所以其重要性是学习 Spring 源码的必修课。

    DefaultListableBeanFactory : 可枚举的Bean工厂。

​ 通过类注释我们可以了解到:DefaultListableBeanFactory 是一个成熟的bean工厂;包含了 bean 定义元数据(beanDefinitionMap),提供了Bean定义的注册和获取方法;管理已存在的Bean实例,而不是基于Bean定义去创建新实例。

2. todo

​ 后续更新 Spring 6 源码阅读系列 @有来技术。

八. 问题整理

在编译过程中,因环境不同每个人可能遇到的问题也都不同,但是总结出来的都是没按照官方文档要求或者自己粗心所致,下面就总结编译中遇到常见的问题,也希望大家在留言区把自己遇到问题记录下。

1. 问题一

  • 报错详情

    D:\SourceCode\spring-framework>gradlew :spring-oxm:compileTestJava
    
    > Task :buildSrc:compileJava FAILED
    D:\SourceCode\spring-framework\buildSrc\src\main\java\org\springframework\build\KotlinConventions.java:44: 错误: 找不到符号
                    freeCompilerArgs.addAll(List.of("-Xsuppress-version-warnings", "-Xjsr305=strict", "-opt-in=kotlin.RequiresOptIn"));
                                                ^
      符号:   方法 of(java.lang.String,java.lang.String,java.lang.String)
      位置: 接口 java.util.List
    1 个错误 FAILURE: Build failed with an exception.
  • 解决方案

    gradlew :spring-oxm:compileTestJava info 查看使用 JDK 的版本是不是17,如果不是请在配置文件 gradle.properties 添加:

    org.gradle.java.home=D:\Java\jdk-17.0.3.1

2. todo

​ 欢迎大家留言区补充或提问~

九. 结语

本篇从 Spring 6 编译依赖的基础环境搭建(JDK17和Gradle)开始、根据官方文档编译源码、在工程新增示例模块测试、以及最后通过对getBean的源码调试,绘制时序图和类注释辅助手段来掌握高效阅读Spring源码技巧。还有一点需要提醒,一定要带着一个明确的目的去看源码,不要被动式的为了学习而学习,不然很容易在知识的海洋里呛水。最后预祝大家编译成功,掌握到属于自己高效阅读源码的方式。

持续更新~

附. 源码

Spring 6 编译源码仓库地址: https://gitee.com/youlaiorg/spring-framework

Spring 6 源码编译和高效阅读源码技巧分享的更多相关文章

  1. 如何在 GitHub 上高效阅读源码?

    原文链接: 如何在 GitHub 上高效阅读源码? 之前听说过一个故事,一个领导为了提高团队战斗力,把团队成员集中起来,搞封闭开发,重点还是在没有网的条件下. 结果就是一个月过去了,产出基本为零. 我 ...

  2. JDK1.8源码分析02之阅读源码顺序

    序言:阅读JDK源码应该从何开始,有计划,有步骤的深入学习呢? 下面就分享一篇比较好的学习源码顺序的文章,给了我们再阅读源码时,一个指导性的标志,而不会迷失方向. 很多java开发的小伙伴都会阅读jd ...

  3. Spring是如何整合JUnit的?JUnit源码关联延伸阅读

    上一篇我们回答了之前在梳理流程时遇到的一些问题,并思考了为什么要这么设计. 本篇是<如何高效阅读源码>专题的第十二篇,通过项目之间的联系来进行扩展阅读,通过项目与项目之间的联系更好的理解项 ...

  4. Java工程师阅读源码的一些见解

    一.为何阅读源码 就是说,通过阅读源码能给你带来什么好处. 学习如何从需求-设计-实现,开阔你的思维,提升你的架构设计能力: 帮助更好地理解原理和架构设计: 帮助更快地定位线上问题BUG 可以根据自己 ...

  5. spring5源码编译过程中必经的坑

    spring源码编译流程:Spring5 源码下载 第 一 步 : https://github.com/spring-projects/spring-framework/archive/v5.0.2 ...

  6. 从ApacheTomcat架构谈面试到源码编译环境v10.0.12

    概述 开启博客分享已近三个月,感谢所有花时间精力和小编一路学习和成长的伙伴们,有你们的支持,我们继续再接再厉 **本人博客网站 **IT小神 www.itxiaoshen.com 定义 Tomcat官 ...

  7. 非寻常方式学习ApacheTomcat架构及10.0.12源码编译

    概述 开启博客分享已近三个月,感谢所有花时间精力和小编一路学习和成长的伙伴们,有你们的支持,我们继续再接再厉 **本人博客网站 **IT小神 www.itxiaoshen.com 定义 Tomcat官 ...

  8. SSH/SSL 源码编译安装简易操作说明

    环境:CentOS 6.7 安全加固需求,由于某盟扫描系统主机有SSL系列漏洞,客户要求必须修复: 解决方案:将SSH/SSL升级到最新版本,删除SSL旧版本(实测不删除旧版本某盟扫描无法通过). 当 ...

  9. Nginx+Php-fpm+MySQL+Redis源码编译安装指南

    说明:本教程由三部分组成如下: 1.      源码编译安装Nginx 2.      源码编译安装php以及mysql.redis扩展模块 3.      配置虚拟主机 文中所涉及安装包程序均提供下 ...

  10. nginx1.11.9 apt即源码编译各平台测试

    测试系统:ubuntu16.04 server,debian8.7 netinstall,centos7 mini. 系统配置:使用virtualbox安装,内存1G,cpu单核,物理CPU  i5- ...

随机推荐

  1. Optional 常用方法总结

    转载请注明出处: Optional 类是 JAVA 8 提供的判断程序是否为空提供的包装工具类:可以减少代码中的 是否为空的判断,以及减少 NullPointerExceptions:使得程序变得更为 ...

  2. Python抖音视频去水印,并打包成exe可执行文件

    前言 抖音里面的视频保存之后,会发现全都带有水印,所以如何解决视频去除水印就很有必要,所以教程来了,本次教程不仅会教大家如何去除视频里的水印,并且教大家将程序制作成exe可执行文件,可以发给你的好友使 ...

  3. vue项目使用.env文件配置全局环境变量

    一.env文件的认识: (1).env 文件主要的作用是存储环境变量,也就是会随着环境变化的东西,比如数据库的用户名.密码.缓存驱动.时区,还有静态文件的存储路径之类的.因为这些信息应该是和环境绑定的 ...

  4. PHP全栈开发(六):PHP与HTML页面交互

    之前我们在HTML表单学习这篇文章里面创建了一个HTML页面下的表单. 这个表单是用户用来输入数据的 具体代码如下 <!DOCTYPE html> <html> <hea ...

  5. 【YOLOv5】LabVIEW+YOLOv5快速实现实时物体识别(Object Detection)含源码

    前言 前面我们给大家介绍了基于LabVIEW+YOLOv3/YOLOv4的物体识别(对象检测),今天接着上次的内容再来看看YOLOv5.本次主要是和大家分享使用LabVIEW快速实现yolov5的物体 ...

  6. MySQL之安装(linux两种版本版本安装)

    LinuxMySQL安装(Mysql5.5版本) 第一种 有安装包的安装方式 1.下载地址: http://dev.mysql.com/downloads/mysql 2.检查当前系统是否安装过mys ...

  7. Azure Kubernetes(AKS)部署及查看应用资源

    简介 上一篇文章讲解了如何使用Azure DevOps持续部署应用到Azure Kubernetes上.但是部署是否成功?会不会遇到什么问题?项目运行中是否会出现问题?我们该怎么样查看这些问题,并且对 ...

  8. 关于IOC容器

    1.什么是 IOC (1)控制反转,把对象创建和对象之间的调用过程,交给 Spring 进行管理 (2)使用 IOC 目的:为了耦合度降低

  9. springboot+vue 实现校园二手商城(毕业设计一)

    1.功能划分 2.实现的效果 2.1 登录页面 2.2 注册页面 2.3 商城首页 2.4 商品详情 2.5 购物车 2.6 订单 2.7 在线交流 2.8 公告信息 2.9 个人信息 3.后台管理界 ...

  10. 齐博x1一段不错的小js提高一点点阅读体验 计算本文阅读所需的时长

    如图所示很多比较大的站点都有这样的一个小玩意 就是本文有多少字 阅读需要多少时间. 一段小小的js就可以实现,当然了php也可以功能太小了不值得做钩子或者插件自己需要的话再模板加一下吧. <sc ...