IDEA 导入 spring 源码

文章目录

  • 前言
  • 一、下载源码
  • 二、安装 Gradle
    • 1. 下载 Gradle
    • 2. 配置环境变量
  • 三、导入前准备
  • 四、编译源码
    • 1. 导入源码
    • 2. 我所遇见的问题
  • 五、测试
    • 1. 创建 module
    • 2. 编写测试代码
    • 3. 我所遇到的问题
  • 六、总结


前言

我们在学习 spring 源码的时候,有时候是需要在阅读源码的时候添加一些代码注释,或者是对源码的一些感悟,如果没有将 spring 的源码导入到 IDEA 中,单纯是通过 Maven 去阅读 jar 的形式是无法添加一些注释信息的,即便可以通过一些比如像 Private Notes 这样的插件做到在源代码中添加注释,但还是有局限性的,首先这个插件不允许你更改源码的行数,所以你的私人注释只能写在一行里,其次导入源代码,你可以更改源代码比如说打印一些东西,都是更有助于去理解源码的。

以下内容是我第一次使用 IDEA 去导入 Spring 源码的一个过程,踩了很多坑,我也记录下我所遇见的问题,以及解决的方案,希望对你有所帮助。


spring 官网:https://spring.io/

一、下载源码

我们可以在 github 或者 gitee 上都能下载到 spring 的源码

github 上下载:

github 上搜索 spring-fremawork 就能找到:https://github.com/spring-projects/spring-framework

IDEA 导入 spring 源码_第1张图片

gitee 上下载:

gitee 上搜索 spring-fremawork 就能找到:https://gitee.com/mirrors/spring-framework?_from=gitee_search

IDEA 导入 spring 源码_第2张图片

虽然说使用可以 git clone 下载源码,但是不太推荐(本人亲自踩过坑,好多问题),这里最好还是直接下载 ZIP 压缩包

我在电脑上创建了 /source-code 这样一个文件夹用于管理我的源代码,然后将下载好的源代码解压缩到该文件夹下,这里我学习的版本是 spring-framework-5.2.x

IDEA 导入 spring 源码_第3张图片


二、安装 Gradle


1. 下载 Gradle

Gradle 是一个构建工具,它类似于 Meven,Spring 就是用 Gradle 进行编译的,所以我们还是下载个 Gradle 会比较好。
IDEA 导入 spring 源码_第4张图片

下载 Gradle 我们一定要找到跟你下载的 Spring 源码兼容的版本,在你下载好的源码中的 \spring-framework-5.2.x\gradle\wrapper\gradle-wrapper.properties 文件中可以查找到应该下载哪个版本的 Gradle

IDEA 导入 spring 源码_第5张图片

所以按照 gradle-wrapper.properties 文件的指定我应该下载 gradle-5.6.4-bin.zip 这个版本的 Gradle

去到官网上下载 https://services.gradle.org/distributions/

IDEA 导入 spring 源码_第6张图片

我创建了一个 /gradle 的文件夹存放刚刚下载好的 Gradle,再进行解压

Gradle 和 Meven 一样都有个仓库,这里为了方便,我把 Gradle 的仓库 .gradle 也创建在这个目录下了

IDEA 导入 spring 源码_第7张图片


2. 配置环境变量

鼠标右键 我的电脑(此电脑) - 属性 - 高级系统设置 再选择 环境变量

添加链接描述

点击 环境变量 进来大概是这样子的,点击 新建

添加链接描述

如下图所示进行配置,配置完成后,点击确定保存配置

配置 GRADLE_HOME

变量名:GRADLE_HOME
变量值:D:\gradle\gradle-5.6.4-bin\gradle-5.6.4(Gradle 的安装目录,也就是 bin 文件夹所在的目录)

IDEA 导入 spring 源码_第8张图片

配置 GRADLE_USER_HOME

变量名:GRADLE_USER_HOME
变量值:D:\gradle\.gradle(Gradle 仓库目录)

IDEA 导入 spring 源码_第9张图片

同时还需要添加 Path 的 配置,选择 Path ,点击 编辑

添加链接描述

新建环境变量:

  • %GRADLE_HOME%\bin
  • %GRADLE_USER_HOME%

IDEA 导入 spring 源码_第10张图片

确定 保存

现在 cmd 打开命令窗口,输入 gradle -v 命令检测 Gradle 是否安装成功

IDEA 导入 spring 源码_第11张图片

能够看到 版本信息 就 ok 了


三、导入前准备

为了加速 gradle 下载依赖包的速度,我们需要在 build.gradlesettings.gradle 这两个文件中添加国内的镜像地址。

IDEA 导入 spring 源码_第12张图片

build.gradle 文件

IDEA 导入 spring 源码_第13张图片

maven { url "https://maven.aliyun.com/nexus/content/groups/public/"}
maven { url "https://maven.aliyun.com/nexus/content/repositories/jcenter"}
maven { url "https://repo.springsource.org/plugins-release"}

settings.gradle 文件

IDEA 导入 spring 源码_第14张图片

maven{ url "https://maven.aliyun.com/nexus/content/groups/public/"}

spring-framework\gradle\wrapper\gradle-wrapper.properties 文件中的 distributionUrl 修改成自己下载的 (PS:这一步可做可不做

IDEA 导入 spring 源码_第15张图片

distributionUrl=file\:///D\:/gradle/gradle-5.6.4-bin.zip

四、编译源码


1. 导入源码

打开 IDEA ,选择 File -> Open

IDEA 导入 spring 源码_第16张图片

选中 spring 源码所在目录

IDEA 导入 spring 源码_第17张图片

导入进来是这样子的

IDEA 导入 spring 源码_第18张图片

项目导进来之后先检查下 JDK 的配置,因为 Gradle JVM 是需要使用 JDK 11,所以务必配置 JDK 11,可以避免很多坑

IDEA 导入 spring 源码_第19张图片

IDEA 导入 spring 源码_第20张图片

然后再配置 Gradle

IDEA 导入 spring 源码_第21张图片

检查下 git 配置(编译的时候会自动去检测 git,所以需要检查下)

IDEA 导入 spring 源码_第22张图片

接下来就等项目自动构建,因为这个过程 Gradle 会下载一些 jar 包需要一些时间。

IDEA 导入 spring 源码_第23张图片

当你看到每一个项目 右下角 基本上都带着一个 蓝色方块,就表示 Spring 的源码导入成功了。

如果你在上述过程中遇到问题,不妨往下面看看 ~~


2. 我所遇见的问题

  1. fatal: not a git repository (or any of the parent directories): .git

IDEA 导入 spring 源码_第24张图片

解决这个问题很简单,进到这层目录下, 调起 Git Bash Here ,依次执行以下三行命令

git init
git add .
git commit -m "随便写点啥都行"

IDEA 导入 spring 源码_第25张图片

在去 IDEA 中重新构建一下就好了

  1. Gradle 版本导致 A problem occurred evaluating root project 'spring'. 等问题

IDEA 导入 spring 源码_第26张图片

之前我是按照 gradle.properties 这个文件下载的 gradle-5.3-bin.zip,我以为够了,没想到 java-test-fixtures 这些包下载不到,没办法,我只能根据 gradle-wrapper.properties 再下载一个 gradle-5.6.4-bin.zip 的版本

IDEA 导入 spring 源码_第27张图片

重新设置一下 IDEA 的 GreadleSpecified location,选择刚下的 Gradle gradle-5.6.4-bin.zip 的版本

IDEA 导入 spring 源码_第28张图片

所以还是要以 gradle-wrapper.properties 文件指定的 Gradle 版本为准会避免掉一些坑

  1. POM relocation to an other version number is not fully supported in Gradle : xml-apis:xml-apis:2.0.2 relocated to xml-apis:xml-apis:1.0.b2

IDEA 导入 spring 源码_第29张图片

我重新构建下就好了,所以也没啥好说的


五、测试


1. 创建 module

现在源码是顺利的导入进来了,那就在 spring 的项目中新建一个 module 来测试一下

右键项目根目录,New -> Module 创建一个 module

IDEA 导入 spring 源码_第30张图片

这个要选 Gradle,点击 Next

IDEA 导入 spring 源码_第31张图片

设置模块名,点击 Finish

IDEA 导入 spring 源码_第32张图片

就 ok 了

IDEA 导入 spring 源码_第33张图片


2. 编写测试代码

IDEA 导入 spring 源码_第34张图片

替换成

IDEA 导入 spring 源码_第35张图片

    testImplementation group: 'junit', name: 'junit', version: '4.13.1'
    testImplementation group: 'org.hamcrest', name: 'hamcrest-core', version: '1.3'
    compile(project(":spring-context"))

这里简单说明以下,Gradle 如果引用的是本项目中的模块,则使用 compile(project(":moduleName)),如果使用的是第三方的包,则使用 testImplementation group:xxxx ' 导入

测试结果:

可以看到是没什么问题的,没有报错,并且使用的类是本项目的,能够正确执行

IDEA 导入 spring 源码_第36张图片

测试代码如下:

UserController.calss

package com.mike.controller;

import com.mike.service.UserService;

public class UserController {

	private UserService userService;

	/**
	 * DI:set 方法注入
	 */
	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public String findAll() {
		return userService.findAll();
	}
}

UserService.java

package com.mike.service;

public interface UserService {

	String findAll();

}

UserServiceImpl.java

package com.mike.service.impl;

import com.mike.service.UserService;

public class UserServiceImpl implements UserService {

	@Override
	public String findAll() {
		return "返回所有用户信息";
	}

}

MainTest.java

package com.mike.test;

import com.mike.controller.UserController;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainTest {

	@Test
	public void test() {
		// 获取 Spring 容器对象
		// 执行这行代码相当于启动了 Spring 容器,解析 spring.xml 文件,并且实例化所有的 bean 对象放到 spring 容器中
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
		// 获取 UserController 对象
		UserController userController = applicationContext.getBean("userController", UserController.class);
		// 执行方法
		String allUsers = userController.findAll();
		System.out.println("allUsers = " + allUsers);
	}
}

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


	<!-- 使用 Spring IOC 和 ID 管理对象 -->
	<bean id="userService" class="com.mike.service.impl.UserServiceImpl"/>

	<bean id="userController" class="com.mike.controller.UserController">
		<property name="userService" ref="userService"/>
	</bean>

</beans>

如果你在上述过程中遇到问题,不妨往下面看看 ~~


3. 我所遇到的问题

  1. build.gradle 怎么配置第三方依赖

比如我写的测试模板中需要 junit,在 pom 文件中我们可以这样导入

        
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.13.1version>
            <scope>testscope>
        dependency>

但是在 build.gradle 文件中我们该怎么去写呢?

其实在 Maven 仓库 中就提供了 Gradle 的导入方式,直接复制过来就行了

IDEA 导入 spring 源码_第37张图片

  1. Kotlin: warnings found and -Weeror specified

在我写完测试代码之后运行 MainTest 类中的 test() 方法所报

IDEA 导入 spring 源码_第38张图片

这个问题出现的原因是 缺少 cglib 和 objenesis 包

解决:在这个目录下调起命令行窗口

IDEA 导入 spring 源码_第39张图片

输入以下两个指令:

gradle objenesisRepackJar
gradle cglibRepackJar

IDEA 导入 spring 源码_第40张图片

  1. java: 找不到符 符号:变量 CoroutinesUtils

解决上一个问题之后再运行 MainTest 类中的 test() 方法所报,这个问题可以说经常会遇到,每构建一次项目都有可能出现

IDEA 导入 spring 源码_第41张图片

这是因为 CoroutinesUtilskotlin 的一个工具类,Spring 源码包读取不到,所以需要手动添加 kotlin-coroutines-X.X.X.BUILD-SNAPSHOT.jarLibraries 中。

点击 File -> Project Structure -> Libraries -> + -> Java

IDEA 导入 spring 源码_第42张图片

然后选择 spring-framework/spring-core/kotlin-coroutines/build/libs/kotlin-coroutines-X.X.X.BUILD-SNAPSHOT.jar 点击 OK (如果你的 kotlin-coroutines 目录下没有 build 目录,跳转到问题3)

IDEA 导入 spring 源码_第43张图片

然后就会跳出一个选择 modules 的页面,选中 spring.spring-core.main 点击 OK

IDEA 导入 spring 源码_第44张图片

  1. kotlin-coroutines 目录下没有 build 目录

如果你和我一样并没有发现

IDEA 导入 spring 源码_第45张图片

点击右侧的 Gradle -> Tasks -> other -> complieKotlin

IDEA 导入 spring 源码_第46张图片

编译之后就有了

  1. compileXXXX 时或者在运行时报错 PropertyComparator无法转换为java.util.Comparator 等各种泛型使用问题

比如 compileKontlin 时

D:\source-code\spring-framework-5.2.x\spring-framework-5.2.x\spring-beans\src\main\java\org\springframework\beans\support\PropertyComparator.java:138: ����: �����ݵ�����: PropertyComparator<CAP#1>�޷�ת��ΪComparator<? super CAP#1>
			source.sort(new PropertyComparator<>(sortDefinition));
			            ^
  ����, CAP#1�������ͱ���:
    CAP#1��?�IJ�����չObject

在这里插入图片描述

或者是运行 main 方法、Test 方法 时

D:\source-code\spring-framework-5.2.x\spring-framework-5.2.x\spring-beans\src\main\java\org\springframework\beans\support\PropertyComparator.java:138:25
java: 不兼容的类型: org.springframework.beans.support.PropertyComparator<capture#1,?>无法转换为java.util.Comparator<? super capture#1,?>

在这里插入图片描述

这个问题感觉是跟泛型有关的坑,我就改了下源码

IDEA 导入 spring 源码_第47张图片

再编译之后这个问题就没有再出现了,不过又出现新的问题

D:\source-code\spring-framework-5.2.x\spring-framework-5.2.x\spring-messaging\src\main\java\org\springframework\messaging\handler\annotation\reactive\PayloadMethodArgumentResolver.java:236: ����: �����ݵ�����: lambda ���ʽ�еķ������ʹ���
							.onErrorResume(ex -> Flux.error(handleReadError(parameter, message, ex)));
							                               ^
    Flux<CAP#1>�޷�ת��ΪPublisher<? extends CAP#1>
  ����, CAP#1�������ͱ���:
    CAP#1��?�IJ�����չObject

IDEA 导入 spring 源码_第48张图片

也跟泛型有关,所以修改这边的代码不是个很好的解决办法,改了一个后续还会遇见很多个,治标不治本

这个问题出现的原因是 gradle jvm 的版本没有使用 jdk 11导致的,所以 Gradle JVM 务必换成 JDK 11

IDEA 导入 spring 源码_第49张图片

Project 的 JDK 也改成 11

IDEA 导入 spring 源码_第50张图片

再编译就没问题了

IDEA 导入 spring 源码_第51张图片


六、总结

以上就是我使用 IDEA 导入 Spring 源码的全过程,不得不说 IDEA 导入 Spring 源码真的有好多的坑啊,不知道多少学习源码的人在这里就被劝退了 ~~

其中还有些错误我没有列举出来,因为这是我优化过后总结出来的,所以另外些错误我没有再遇到过就不写在这上面了,在这个过程中觉得最大的阻碍就是对 Gradle 的不熟悉,很多问题都跟 Gradle 有关,好在最后都解决了,也希望这篇文章能够让你在学习源码的过程中有个好的开头。


参考博客:
《Spring》第一篇 IDEA导入Spring源码:https://blog.csdn.net/weixin_44167408/article/details/121769949
知乎:spring源码编译的过程和问题:https://zhuanlan.zhihu.com/p/378831634

你可能感兴趣的:(源码解读,踩坑系列,spring,intellij-idea,java)