gradle 编译 Spring 源码(亲测有效)

2023-11-18

天知道我今天下午经历了什么!从去年开始断断续续看源码,在 IDEA 中 Spring 源码只读不能写,所以每次都是将方法拷贝到 vscode 中。IDEA 中看代码逻辑,接着在 vscode 对应的方法上写注释。期初这种方式没觉得有什么不便,但是看得越来越多,代码的调用也越来越复杂,这种“复制”的方式就有问题了,代码层次没有,就是保存也很不方便。那最好的方式是直接在源码上写注释,用 git 工具做版本控制,So 就有了编译源码的想法。

理想很丰满,现实很骨感!一个掉头发的下午,还是在劳动节。搞定后觉得就是几个细节没有理清楚,写篇博客记录下,后面的人少采点坑。

1. 准备工作

我的配置是:Spring 5.2.14,Gradle 5.6.4,JDK 8,IDEA 2021。

默认 JDK 8 已经安装了。

1.1 下载 Spring 5.2.14 源码

git clone https://github.com/spring-projects/spring-framework.git
cd spring-framework
git reset --hard 4ceacfa70c37596c46147a5c2b56f07e470643d8

1.2 下载 Gradle 5.6.4

这个不是手动下载的,在命令行工具中执行编译命令时,会主动去本地目录 /.gradle/wrapper/dists/ 找有没有 5.6.4 这个版本,如果没有就下载。这里怎么确定要使用 5.6.4 版本呢?

cat spring-framework/gradle/wrapper/gradle-wrapper.properties

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

gradle-wrapper.properties 文件中写了编译源码要求的 gradle 版本。

2. 修改几个配置

这里修改配置只是为了让编译能快一些,因为编译时会下载依赖,墙的缘故,将依赖源改成国内阿里源会快很多。

build.gradle

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

grade.properties

# 这个版本指的是 spring 源码的版本,不是 gradle 的,别瞎改。
version=5.2.14.RELEASE
org.gradle.jvmargs=-Xmx2048M
## 开启 Gradle 缓存
org.gradle.caching=true
## 开启并行编译
org.gradle.parallel=true
## 启用新的孵化模式
org.gradle.configureondemand=true
## 开启守护进程 通过开启守护进程,下一次构建的时候,将会连接这个守护进程进行构建,而不是重新fork一个gradle构建进程
org.gradle.daemon=true

settings.gradle

pluginManagement {
	repositories {
        // 加这个
		maven { url "https://maven.aliyun.com/repository/public" }
    gradlePluginPortal()
		maven { url 'https://repo.spring.io/plugins-release' }
	}
}

2. 编译

源码根目录下的 import-into-idea.md 文件中已经写了。

1. Precompile `spring-oxm` with `./gradlew :spring-oxm:compileTestJava`
2. Import into IntelliJ (File -> New -> Project from Existing Sources -> Navigate to directory -> Select build.gradle)
3. When prompted exclude the `spring-aspects` module (or after the import via File-> Project Structure -> Modules)
4. Code away
# -------------
1. 在源码根目录下执行命令:./gradlew :spring-oxm:compileTestJava。
2. 按照箭头的顺序,一直定位到源码的 build.gradle 文件打开。
3. 源码里没有 `spring-aspects` module 模块。
4. 使用代码。

在源码根目录下执行 ./gradlew :spring-oxm:compileTestJava 执行编译。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LQOb9Hep-1620054758234)(https://raw.githubusercontent.com/diego1109/pictures/main/20210503214830.png)]

本地没有,先下载 Gradle 5.6.4,再编译源码。这里是可以直接编译成功的,有些博客中写着导入到 IDEA 中再编译,我觉得那样就更麻烦,因为还得自己配使用那个 gradle,好些时候是导入了代码,忘了该配置,出现了不兼容还不知道问题在哪。(这个后面再说)

接下来就是打开 IDEA 导入 build.gradle 文件了,导入后等着,不需要任何手动配置 IDEA 自己执行 sync ,完毕后就能直接使用了。

3. 测试

IDEA 说 “SUCCESSFUL” ,我们还得自己测试一下到底能不能用。

3.1 创建一个新的 Module

image-20210503220406536 image-20210503220310539 image-20210503220310539

创建完成后的测试项目目录:

# tree test-spring-source -L 3
test-spring-source
├── build.gradle
└── src
    ├── main
    │   ├── java
    │   └── resources
    ├── test
    │   ├── java
    │   └── resources
    └── testFixtures
        ├── java
        └── resources

3.2 写测试逻辑

修改 build.gradle

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
    // 添加依赖
    implementation(project(":spring-context"))
}
image-20210503222348368

Main.java

package com;

import com.config.AppConfig;
import com.domain.User;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
  public static void main(String[] args){
    // 创建 context ,并向其注册一个 User bean。
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    // 将 User bean 拿出来。
    User user =  context.getBean(User.class);
    // 查看内容。
    System.out.println("name: "+ user.getName());
    System.out.println("age: "+ user.getAge());
  }
}

AppConfig.java

package com.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.domain")
public class AppConfig {
}

User.java

package com.domain;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class User {

  @Value("diego")
  private String name;
  @Value("100")
  private int age;

  public String getName() {
    return name;
  }

  public int getAge() {
    return age;
  }
}

最终目录结构:

test-spring-source
├── build.gradle
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       ├── Main.java
    │   │       ├── config
    │   │       │   └── AppConfig.java
    │   │       └── domain
    │   │           └── User.java
    │   └── resources
    ├── test
    │   ├── java
    │   └── resources
    └── testFixtures
        ├── java
        └── resources

运行结果:

> Task :test-spring-source-code:Main.main()
name: diego
age: 100

4. 踩的坑

**兼容问题:**Spring 版本,Gradle 版本,JDK 版本,编译失败都得归功于这三个不兼容。先确定 JDK 的版本,再去找 JDK 能支持的 spring 版本 和 gradle 版本。

spring:https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Versions。

gradle:https://docs.gradle.org/current/userguide/compatibility.html。

你编译时用的是哪个版本的 Gradle?

这先得回答一台电脑上怎么会出现多个 gradle 版本的?

image-20210503223814241

这三条命令应该能说明问题了。首先电脑上肯定装了 gradle 这先是一个版本,此电脑上装的是 6.5.1。但是 gradle 是不断更新的工具,它会有版本迭代,而不同的 Spring 项目可能会用到不同版本的 gradle。这时候怎么办?升级或者降级 6.5.1,显然不靠谱。采用的方式是 当 spring 项目启动时,先检查其所要求的版本在本地有没有,如果没有,那先下载该版本,并保存到本地的 ~/.gradle/wrapper/dists 目录下,这就解释了为什么一台电脑上会出现多个 gradle 版本。

如果本地有多个版本,spring 项目编译时用哪个?

至于使用哪个,在 spring 项目的 gradle/wrapper/gradle-wrapper.properties 定义了,可以翻上去看看。

使用命令行工具,这里没什么大碍。

但如果使用 IDEA编译,坑货来了。使用 IDEA 编译失败,多半这里有鬼。原因是 IDEA 使用哪个版本编译,是要手动配置的。如果默认的正好符合,那完事大吉,如果不符合,开发者有忘了这里,那坑死人不偿命。

image-20210503225907400quan

圈住的地方是用来设置:本项目到底使用哪个 gradle。

gradle-wrapper.properties : IDEA 推荐的方式,gradle 来源于项目的 gradle-wrapper.properties 中定义的版本。

wrapper task in Gradle build script:task 中定义的,如果开发者喜欢控制 gradle 版本,可以使用这种方式。

Specified location:开发者自己指定一个版本的 gradle 所在的目录。

gradle-setting更详细的信息。

最后想写的是:猜到坑了要淡定、要坚持。可以晚一点吃饭,可以晚一会上厕所,因为屁股离开凳子,等再坐上来就没了之前的感觉了。别拖。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gradle 编译 Spring 源码(亲测有效) 的相关文章

随机推荐

  • JQuery全部过滤选择器详细介绍下

    文章目录 JQuery全部过滤选择器详细介绍 下 属性过滤选择器 属性过滤选择器 应用实例 代码演示 子元素过滤选择器 子元素过滤选择器基本介绍 5 nth child 选择器详解如下 子元素过滤选择器示例 应用实例 代码演示 表单属性过滤
  • SpringBoot整合Swagger

    一 Swagger 认识Swagger Swagger 是一个规范和完整的框架 用于生成 描述 调用和可视化 RESTful 风格的 Web 服务 总体目标是使客户端和文件系统作为服务器以同样的速度来更新 文件的方法 参数和模型紧密集成到服
  • 开关电源Buck电路CCM及DCM工作模式

    一 Buck开关型调整器 二 CCM及DCM定义 1 CCM ContinuousConduction Mode 连续导通模式 在一个开关周期内 电感电流从不会到0 或者说电感从不 复位 意味着在开关周期内电感磁通从不回到0 功率管闭合时
  • (详解与使用)Sharding-JDBC通过mysql主从复制来进行项目优化

    目录 背景 一 环境准备 1 mysql的主从复制环境 2 导入maven坐标 3 在配置文件 application yml 中配置读写分离规则 4 在配置文件中配置允许bean定义覆盖配置项 5 配置完毕可以测试 背景 面对日益增加的系
  • 安可与普通测评的区别_订房网站比较,Agoda、Booking、Hotels、Expedia和携程的区别,哪个更好更便宜...

    经常在网上看到不少网友在订房过程中会提出这样的问题 Agoda和Booking有什么区别 Agoda和携程哪个好 Hotels订房靠谱吗 订酒店哪个网站最便宜 Agoda Booking还是Expedia 等等 今天我们就来介绍一下 五大主
  • GitLab 简易指引(一):离线一键安装

    本文为 原创 文章 转载请标明出处 原文链接 https weyunx com 2019 01 22 原文出自 微云的技术博客 前言 近期为满足持续集成的需要 需要在内网搭建GitLab GitLab 简介 GitLab 是利用 Ruby
  • 把频谱图的纵坐标设置为分贝刻度

    在信号的频谱分析中 有时频谱的幅值有很大的动态范围 必须要把幅值取对数转换成为分贝值 有两种解决方法 一种是Y轴用对数坐标 另一种是对幅值取对数 转换成分贝值后再画图 1 Y轴用对数坐标 作图时 Y轴用对数坐标 在MATLAB中 X轴 Y轴
  • spring boot 集成logstash 日志

    1 logstash 插件配置 logstash下config文件夹下添加 test conf 文件内容 input tcp mode gt server host gt 0 0 0 0 port gt 4567 codec gt json
  • 已解决 AttributeError: module ‘tensorflow‘ has no attribute ‘random‘

    今天运行py文件的时候发现出了这个错 用了很多方法都没能解决 删了重装已经试了无数次了也不行 于是我把tensorflow的版本给升级了一下 解决问题了 之前是1 10的我升到了1 12 pip install tensorflow gpu
  • linux:vim NERDTree 安装和使用

    1 安装NERDTree之前按照网上的按照一直都安装不上 现在安装上了笔记一下 现在NERDTree 提供两种下载方法 http www vim org scripts script php script id 1658 https git
  • Linux系统通过Console线连接交换机

    Linux系统通过Console口连接交换机 安装minicom Ubuntu安装 sudo apt get install minicom Centos 安装 sudo yum install minicom 配置minicom 需要ro
  • 页面增加水印,附带vue3写法

    效果图 App vue文件
  • cmake简单使用

    概述 cmake是一种跨平台编译工具 除了可以编译c c 代码也可以编译其他语言的代码 其主要就是通过cmake执行CMakeLists txt从而生成Makefile 下面就自己了解到的简单的一点知识 做以记录 更多可查看官网 https
  • python二叉树类定义,列表转二叉树,leetcode本地调试

    如果想用本地IDE调试leetcode上的题目 可以使用以下辅助类 二叉树类定义 Definition for a binary tree node class TreeNode def init self x self val x sel
  • AIX5.3 weblogic9.2速度很慢问题的解决过程

    问题描述 开始的时侯采用的是32位JDK 但是部署应用的时侯总是out of memory 后来改用64位JDK 使用64位JDK之后没有aix 64位 native lib 最后从BEA工程师那取得了64位lib依然无法使用 没有使用na
  • python面试题:Python 剪绳子的多种思路实现(动态规划和贪心)

    本文来源于公众号 csdn2299 喜欢可以关注公众号 程序员学府 这篇文章主要介绍了Python 剪绳子的多种思路实现 动态规划和贪心 文中通过示例代码介绍的非常详细 对大家的学习或者工作具有一定的参考学习价值 需要的朋友们下面随着小编来
  • MyBatis-Plus开启AR功能

    开启AR功能领域模型 1 实体类开启AR 同时开启Dao层AR 继承MP特殊类Model
  • echarts x轴数据过多左右滚动显示

    dataZoom使用让出现X轴的滚动条 dataZoom type slider show true xAxisIndex 0 start 0 end 100 textStyle color ccd7d7 或者代码 dataZoom sta
  • 使用ray对pytorch模型进行超参数调节

    def main num samples 10 max num epochs 10 gpus per trial 1 data dir os path abspath data load data data dir config l1 tu
  • gradle 编译 Spring 源码(亲测有效)

    天知道我今天下午经历了什么 从去年开始断断续续看源码 在 IDEA 中 Spring 源码只读不能写 所以每次都是将方法拷贝到 vscode 中 IDEA 中看代码逻辑 接着在 vscode 对应的方法上写注释 期初这种方式没觉得有什么不便