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()'.
以上就是今天的全部内容,有问题欢迎评论区交流~~