Spring源码构建(一次成功)

1.前言

        Spring在java开发领域已然是必不可少的框架,在我们日常开发过程中不仅仅会使用它,而且需要明白它的一些基本原理和机制,在找工作面试的过程中也是几乎必考的问题,这里就需要翻阅Spring的源码进行学习,阅读源码的好处想必就不必过多言语。结合网络上各种各样的源码构建教程也是五花八门,很多人都是各种踩坑之后也没成功,笔者也是在翻阅了很多篇博客之后不下于5次构建最终才成功.....真是酸爽(应该是本人过于菜鸡[手动滑稽])。

首先将本次源码构建的环境列出说明:

  • Windows-11

  • idea-2023.2.5

  • jdk-1.8.0_381

  • Spring-5.3.0-SNAPSHOT

  • gradle-6.5

基于以上环境是一次性构建成功,也遇到一些问题,下面会详细说明。

2.Spring构建

2.1.下载安装gradle

        这个不是本文重点并且安装简单所以只是简单介绍,安装有的会去官网安装,但是这个下载速度实在是太感人了......推荐一个腾讯提供的高速下载镜像地址,下载速度飞起而且版本挺全的:腾讯gradle镜像地址

选择好对应的版本之后,找到一个没有空格及中文的目录解压,推荐搞一个专门存放开发环境的文件夹,解压后目录结构如下:

然后在系统环境变量中配置环境变量,具体配置如下:

上面第二个环境变量就是gradle下载依赖存放的位置,可以想象成maven中的repository仓库(变量名最好就叫GRADLE_USER_HOME,下面修改源码中的gradle-wrapper.properties文件会用到)。然后在Path中增加:

以上内容配置完成后,任意目录下按下win+r打开cmd,执行gradle -v,输出以下内容后即配置成功。

2.2.下载Spring源码

在GitHub上下载Spring源码,也可以去Gitee中下载,具体下载过程自行百度。重点是下面内容,解压完之后修改一些配置项:

1、import-into-idea.md:这是官方提供的spring源码导入idea的步骤和注意说明,内容大致如下

以下是针对 IntelliJ IDEA 2016.2.2进行的测试。

步骤

在本地克隆的 spring-framework框架的工作目录里:

  • 使用./gradlew :spring-oxm:compileTestJava命令预编译spring-oxm项目。

  • 导入IntelliJ IDEA(通过File -> New -> Project from Existing Sources -> Navigate to directory -> Select build.gradle)

  • 当提示排除spring-aspects模块时(或者在导入之后通过File-> Project Structure -> Modules)

  • 继续编码

已知问题

  • 1.spring-core和spring-oxm由于重新打包的依赖项需要先进行预编译。(可以通过 https://youtrack.jetbrains.com/issue/IDEA-160605查看构建的*RepackJar任务)

  • 2.由于引用了IntelliJ IDEA不知道的aspects类型,所以“spring-aspects”不能编译,可以在https://youtrack.jetbrains.com/issue/IDEA-64446查看详情。意味着,可以将“spring-aspects”从项目中排除,以避免编译错误。

  • 3.虽然JUnit测试通过Gradle命令行,但有些测试在使用IntelliJ IDEA运行时可能会失败。这个问题仍在解决中。如果试图从IntelliJ IDEA中运行所有的JUnit测试,您可能需要设置以下VM选项以避免内存不足错误: -XX:MaxPermSize=2048m -Xmx2048m -XX:MaxHeapSize=2048m

  • 4.如果您在IDE中调用“Rebuild Project”,则必须再次生成一些使用spring-oxm模块的测试资源(通过命令./gradlew:spring-oxm:compileTestJava)

小贴士

在任何情况下,请不要签入您自己生成的.iml,.ipr或.iws文件。您会注意到,这些文件已经被有意义的放在了.gitignore中。同样的策略也适用于eclipse元数据。

常见问题

问. IntelliJ IDEA 自己的gradle支持怎么样(https://confluence.jetbrains.net/display/IDEADEV/Gradle+integration)?

答. 请留意 https://youtrack.jetbrains.com/issue/IDEA-53476

2、修改settings.gradle文件,下载依赖的网络速度几乎是龟速,我们加上阿里云的maven镜像仓库。

maven { url "https://maven.aliyun.com/repository/public" }

注意要注释掉://id "io.spring.gradle-enterprise-conventions" version "0.0.2",不然构建过程中会报错。

修改之后如下图所示:

3、修改gradle.properties文件

version=5.3.0-SNAPSHOT
## 设置此参数主要是编译下载包会占用大量的内存,可能会内存溢出
org.gradle.jvmargs=-Xmx2048M
## 开启 Gradle 缓存
org.gradle.caching=true
## 开启并行编译
org.gradle.parallel=true
## 启用新的孵化模式
org.gradle.configureondemand=true
## 开启守护进程 通过开启守护进程,下一次构建的时候,将会连接这个守护进程进行构建,而不是重新fork一个gradle构建进程
org.gradle.daemon=true

4、修改build.gradle文件,大约在282行左右,加上阿里云镜像仓库提高下载速度。

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

5.修改源码中的gradle-wrapper.properties文件,在spring-framework-master\gradle\wrapper中。

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
#distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip   #这里是在线安装,很慢,所以选择本地的。
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
#这里是本地gradle安装路径,注意:最好和上面的distributionUrl中的gradle版本保持一致,不然可能出现不兼容问题。
distributionUrl=file:///D:/tools/Gradle/gradle-6.5-bin.zip  

2.3.开始构建

        大部分博主推荐在导入IDE之前进行预编译spring-oxm和spring-core,但是笔者在这个过程中遇到了一些问题,我这里是先导入idea后编译spring-oxm和spring-core模块也是可以的。首先代码导入idea:

2.3.1.代码导入

依次点击File->New->Project from Existing Sources,选择源码包路径下的build.gradle文件完成源码导入。

2.3.2.idea配置gradle

可以预先打开idea配置,也可在导入过程中去配置,这个不要紧。操作路径:File->Setting->Build,Execution,Deployment->Build Tools->Gradle。

2.3.3.依赖问题

        在编译过程中下载依赖的时候可能会出一个依赖找不到的错误,具体报错日志找不到了,反正就是跟 io.rsocket:rsocket-bom:1.0.1 依赖项相关的,把 io.rsocket:rsocket-bom:1.0.1-SNAPSHOT 改成 io.rsocket:rsocket-bom:1.0.1 即可(没有出现此问题直接忽略)。

2.3.4等待构建成功

        以上设置完成后就是等待过程了,具体多长时间看网速,我的导入编译完成耗时约4m 56s,一次性成功。编译日志内容如下:

Starting Gradle Daemon...
Gradle Daemon started in 4 s 477 ms
> Task :buildSrc:compileJava
> Task :buildSrc:compileGroovy NO-SOURCE
> Task :buildSrc:pluginDescriptors
> Task :buildSrc:processResources
> Task :buildSrc:classes
> Task :buildSrc:jar
> Task :buildSrc:assemble
> Task :buildSrc:pluginUnderTestMetadata
> 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:validateTaskProperties
> Task :buildSrc:check
> Task :buildSrc:build
​
CONFIGURE SUCCESSFUL in 4m 56s

        到这里可能会出现一个问题,就是在编译过程中会报Decoder接口中的MonoProcessor类的错,我这里没有配置ideaVM中的编码格式所以是乱码,配置完之后整个idea字体变形了重新设置也没有,不知道是不是idea版本bug.......这不是重点,重点是报的错误意思就是该类已被标记为过时,解决问题就是把CompilerConventionsPlugin类中的 "-Werror" 注释掉重新build即可,一次不行再build,我就是这么解决的。

2.3.5.预编译spring-oxm和spring-core

在idea中打开Terminal菜单,在源码目录下进入cmd也行,依次执行以下命令:

./gradlew :spring-oxm:compileTestJava
./gradlew :spring-core:compileTestJava

报命令语法错误的就把 ./ 去掉。

到此,源码构建过程完毕!

3.测试

在以下目录创建相关测试类:

SysConfig:

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

@Configuration
public class SysConfig {
​
    @Bean
    public User user(){
        return new User("zs",18);
    }
}

User:

public class User {
    private String name;
    private Integer age;
​
    public User() {
    }
​
    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public Integer getAge() {
        return age;
    }
​
    public void setAge(Integer age) {
        this.age = age;
    }
​
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

TestMy:

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
​
public class TestMy {
​
    // 测试spring构建是否成功
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SysConfig.class);
        User user = (User)applicationContext.getBean("user");
        System.out.println("====================" + user);
    }
}

运行日志如下,成功打印出User对象的内容,证明构建成功,没有问题:

10:35:52: Executing ':spring-context:TestMy.main()'...
​
> 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
Configuration on demand is an incubating feature.
> Task :spring-core:cglibRepackJar UP-TO-DATE
> Task :spring-aop:processResources UP-TO-DATE
> Task :spring-beans:processResources UP-TO-DATE
> Task :spring-expression:processResources UP-TO-DATE
> Task :spring-aop:processTestFixturesResources NO-SOURCE
> Task :spring-beans:processTestFixturesResources NO-SOURCE
> Task :spring-context:processResources UP-TO-DATE
> Task :spring-core:objenesisRepackJar UP-TO-DATE
> Task :spring-context:processTestFixturesResources NO-SOURCE
> Task :spring-core:processResources UP-TO-DATE
> Task :spring-core:processTestFixturesResources NO-SOURCE
> Task :spring-instrument:compileJava UP-TO-DATE
> Task :spring-instrument:processResources NO-SOURCE
> Task :spring-instrument:classes UP-TO-DATE
> Task :kotlin-coroutines:compileKotlin UP-TO-DATE
> Task :spring-instrument:jar UP-TO-DATE
> Task :kotlin-coroutines:compileJava NO-SOURCE
> Task :kotlin-coroutines:processResources NO-SOURCE
> Task :kotlin-coroutines:classes UP-TO-DATE
> Task :kotlin-coroutines:inspectClassesForKotlinIC UP-TO-DATE
> Task :kotlin-coroutines:jar UP-TO-DATE
> Task :spring-context:processTestResources UP-TO-DATE
> Task :spring-jcl:compileJava UP-TO-DATE
> Task :spring-jcl:processResources UP-TO-DATE
> Task :spring-jcl:classes UP-TO-DATE
> Task :spring-jcl:jar UP-TO-DATE
> Task :spring-core:compileKotlin UP-TO-DATE
> Task :spring-core:compileJava UP-TO-DATE
> Task :spring-core:classes UP-TO-DATE
> Task :spring-core:inspectClassesForKotlinIC UP-TO-DATE
> Task :spring-core:jar UP-TO-DATE
> Task :spring-expression:compileKotlin UP-TO-DATE
> Task :spring-expression:compileJava UP-TO-DATE
> Task :spring-expression:classes UP-TO-DATE
> Task :spring-core:compileTestFixturesKotlin UP-TO-DATE
> Task :spring-beans:compileGroovy UP-TO-DATE
> Task :spring-expression:inspectClassesForKotlinIC UP-TO-DATE
> Task :spring-expression:jar UP-TO-DATE
> Task :spring-beans:compileKotlin UP-TO-DATE
> Task :spring-beans:compileJava NO-SOURCE
> Task :spring-beans:classes UP-TO-DATE
> Task :spring-beans:inspectClassesForKotlinIC UP-TO-DATE
> Task :spring-beans:jar UP-TO-DATE
> Task :spring-beans:compileTestFixturesKotlin UP-TO-DATE
> Task :spring-aop:compileJava UP-TO-DATE
> Task :spring-aop:classes UP-TO-DATE
> Task :spring-aop:jar UP-TO-DATE
> Task :spring-context:compileKotlin UP-TO-DATE
> Task :spring-context:compileJava UP-TO-DATE
> Task :spring-context:compileGroovy NO-SOURCE
> Task :spring-context:classes UP-TO-DATE
> Task :spring-context:inspectClassesForKotlinIC UP-TO-DATE
> Task :spring-context:jar UP-TO-DATE
> Task :spring-core:compileTestFixturesJava
> Task :spring-core:testFixturesClasses
> Task :spring-core:testFixturesJar UP-TO-DATE
> Task :spring-beans:compileTestFixturesJava
> Task :spring-beans:compileTestFixturesGroovy NO-SOURCE
> Task :spring-beans:testFixturesClasses
> Task :spring-beans:testFixturesJar UP-TO-DATE
> Task :spring-context:compileTestFixturesKotlin UP-TO-DATE
> Task :spring-aop:compileTestFixturesJava
> Task :spring-aop:testFixturesClasses
> Task :spring-aop:testFixturesJar UP-TO-DATE
> Task :spring-context:compileTestFixturesJava
> Task :spring-context:compileTestFixturesGroovy NO-SOURCE
> Task :spring-context:testFixturesClasses
> Task :spring-context:testFixturesJar UP-TO-DATE
> Task :spring-context:compileTestKotlin
​
> Task :spring-context:compileTestJava
​
> Task :spring-context:compileTestGroovy
> Task :spring-context:testClasses
​
// 看这里,成功打印出User对象属性
> Task :spring-context:TestMy.main()
====================User{name='zs', age=18}
​
Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.5/userguide/command_line_interface.html#sec:command_line_warnings
​
BUILD SUCCESSFUL in 15s
49 actionable tasks: 8 executed, 41 up-to-date
10:36:08: Execution finished ':spring-context:TestMy.main()'.

以上就是今天的全部内容,有问题欢迎评论区交流~~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

「已注销」

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值