Spring 6 源码编译和高效阅读源码技巧分享

news2024/11/20 9:25:02

一. 前言

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.2D:\SourceCode\spring-framework
Java环境JDK 17D:\Java\jdk-17.0.3.1
编译工具Gradle 7.6D:\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)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G4t5uPHh-1670807292624)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/955224eb54bc455a98cdaf31aae3be48~tplv-k3u1fbpfcp-zoom-1.image)]

查看版本 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源码仓库地址:

地址备注
Githubhttps://github.com/spring-projects/spring-framework.git速度慢
GitCodehttps://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. 测试代码

代码结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aJlv6qAe-1670807292651)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0619225e2eaa4e599fb00f3ab498cba3~tplv-k3u1fbpfcp-zoom-1.image)]

/**
 * 人接口
 */
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

image-20221210232239371

七. 源码阅读

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

1. getBean 源码

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

image-20221210230131704

image-20221210230131704

  • 加深理解记忆: 基于调用栈绘制时序图(IDEA的PlantUML插件)

    时序图源文件:https://gitee.com/youlaiorg/spring-framework/blob/master/doc/diagram/getBean.puml

getBean时序图

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/81886.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

风靡互联网关键词 Web3.0 | 区块链 | 元宇宙……

💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! Web web是互联网的总称,全称为World Wide Web,缩写WWW ,即全球广域网,也称为万维网,它是一种基于超文本和H…

nacos--基础--1.4--理论--原理

nacos–基础–1.4–理论–原理 1、基本架构 2、Nacos 原理 2.1、信息的同步主要的几种方式 push (服务端主动push)pull (客户端的轮询), 超时时间比较短long pull (超时时间比较长) 2.2、配置中心原理 nacos 配置中心就是采用:客户端 long pull 的方式…

新体制SAR——BiDi SAR

1. 概述 TerraSAR的相控阵天线具备方位向和距离向二维电扫能力,在这一能力的基础上,TerraSAR可以工作在条带模式、ScanSAR模式、滑聚模式和TOPS模式(TOPS是实验模式,不是主模式)。载荷的PRF可以设计在3-6.5kHz&#xf…

【笔试强训】Day 7

🌈欢迎来到笔试强训专栏 (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是Scort目前状态:大三非科班啃C中🌍博客主页:张小姐的猫~江湖背景快上车🚘,握好方向盘跟我有一起打天下嘞!送给自己的一句鸡汤&#x…

安科瑞AcrelEMS-SW智慧水务能效管理平台解决方案

系统概述 安科瑞电气具备从终端感知、边缘计算到能效管理平台的产品生态体系,AcrelEMS-SW智慧水务能效管理平台通过在污水厂源、网、荷、储、充的各个关键节点安装保护、监测、分析、治理装置,用于监测污水厂能耗总量和能耗强度,重点监测主要…

2022年史上最全Java面试题:数据结构+算法+JVM+线程+finalize+GC

基本概念 操作系统中 heap 和 stack 的区别 什么是基于注解的切面实现 什么是 对象/关系 映射集成模块 什么是 Java 的反射机制 什么是 ACID BS与CS的联系与区别 Cookie 和 Session的区别 fail-fast 与 fail-safe 机制有什么区别 get 和 post请求的区别 Interface 与 …

服务端高并发分布式架构演进之路

1. 概述 本文以淘宝作为例子,介绍从一百个到千万级并发情况下服务端的架构的演进过程。同时列举出每个演进阶段会遇到的相关技术,让大家对架构的演进有一个整体的认知。文章最后汇总了一些架构设计的原则。 特别说明:本文以淘宝为例仅仅是为…

如何入门学python,这是很值得借鉴的学习方法

前言 众所周知,python的应用领域十分广泛,无论是对于专业的程序员还是从事其他工作的人,python这门编程语言都非常值得学习。 但对于零基础的人来说,该如何入门python编程呢? 虽然现在网上有关python编程的教程很多…

PyFlink系列之一:PyFlink安装和PyFlink使用的详细技术

PyFlink系列之一:PyFlink安装和PyFlink使用的详细技术一、下载PyFlink二、创建TableEnvironment三、TableEnvironment API1.Table/SQL 操作2.执行/解释作业3.创建/删除用户自定义函数4.依赖管理5.配置四、Catalog APIs五、Statebackend,Checkpoint 以及重…

小程序图片加载失败binderror方法处理

场景:我们在小程序项目中的一个图片列表,当某些图片加载失败后,直接显示空白,这样用户体验不好,为了解决当图片加载失败,我们给一个默认图片代替,参考官方给的图片加载失败的处理方法&#xff1…

C51单片机开发程序报错 main.c (11) : error C267 : ‘Func‘ : requires ANSI-style prototype

问题 C51单片机开发程序报错 main.c (11) : error C267 : Func : requires ANSI-style prototype详细问题 问题一 问题二 问题三 可能原因一 函数定义声明处(.h文件中)与主函数中函数(函数名/参数类型/返回值类型)不一致 解决…

【Vue2+Element ui通用后台】项目搭建和vue-router使用

文章目录介绍创建项目并引入Element-ui按需引入全局引入vue-router安装嵌套路由介绍 通过这个系列文章,我们将学到: 1.项目搭建使用element实现首页布局 2.顶部导航菜单及与左侧导航联动的面包屑实现 3.封装—个ECharts组件 4.封装一个Form表单组件和Ta…

木字楠后台管理系统开发(4):SpringSecurity引入并编写登陆接口

🎶 文章简介:木字楠后台管理系统开发(4):SpringSecurity引入并编写登陆接口 💡 创作目的:为了带大家完整的体验木字楠后台管理系统模版的开发流程 ☀️ 今日天气:冬天来啦! 📝 每日一…

在ubuntu上部署gitlab详细步骤

一、Ubuntu安装gitlab步骤: 安装依赖 通过快捷键ctrlaltT打开命令行窗口,然后运行下面两行命令 sudo apt update sudo apt-get upgrade sudo apt-get install curl openssh-server ca-certificates postfix 如果这一步遇到下面提示界面&#xff0c…

BUUCTF Web2

[HCTF 2018]admin flask session的伪造 改密码的页面源码有提示,得到秘钥ckj123 自己的session .eJw9kEGLwjAUhP_KkrOHJm09CB5cbKULeaHwanm5iKu1adK4UBVpxP--XRc8zGmGj5l5sN1paC6GLa7DrZmxXXdkiwf7-GYLptCl2uoOcHWXmDu1kYnGLIFNdQdsBYmtkbb3YI89YDXKUHKNTkCg8S9PliJ…

Kotlin 开发Android app(二十二):Retrofit和简单的mvp框架

到这一节,基本上把大部分kotlin和android的开发都已经介绍完成了,通过了前面和这一章的框架结构,基本上能解决开发中的很多问题,并且能够知道android的主要的技术,并进行独立开发了。对于传统的开发的话,还…

一些可以显著提高大型 Java 项目启动速度的尝试

我们线上的业务 jar 包基本上普遍比较庞大,动不动一个 jar 包上百 M,启动时间在分钟级,拖慢了我们在故障时快速扩容的响应。于是做了一些分析,看看 Java 程序启动慢到底慢在哪里,如何去优化,目前的效果是大…

SpringSecurity安全框架

目录 一、Spring Security介绍 1、框架介绍 2、认证与授权实现思路 二、整合Spring Security 1、在common下创建spring_security模块 2、在spring_security引入相关依赖 3.代码结构说明: 4、创建spring security核心配置类 5、创建认证授权相关的工具类 &a…

Roson的Qt之旅 #139 Qt读写Excel

1.使用QAxObject读写Excel QAxObject类提供了一个包裹COM对象的QObject。 QAxObject可以被实例化为一个空的对象,用它应该包裹的COM对象的名字,或者用一个指向代表现有COM对象的IUnknown的指针。如果COM对象实现了IDispatch接口,该对象的属性…

【Python 身份证JSON数据读取】——身份证前六位地区码对照表文件(最全版-JSON文件)

点个赞留个关注吧!! 1、生成身份证前六位地区码对照表JSON文件 2、python 读取JSON文件 提取码【1234】 json文件下载 废话不多说,先上效果图 一、生成身份证json数据文件 先去百度搜索地区身份证号码前6位查询 ,然后进入网站控制台界面&…