前言

工欲善其事必先利其器。学习和深读Spring源码一个重要的前提:编译源码到我们的本地环境。这样方便我们在本地环境添加注释、断点追踪、查看类或接口的继承关系等等,更加高效的学习Spring源码。个人觉得深读Spring源码对我们的编码水平会有很大很大的提升,因为其牵涉的广度、深读、以及优秀编码规范都值得我们去品、细品、慢慢品。废话不多说,本篇就如何在我们的intelliJ IDEA编译Spring源码的步骤以及在编译的过程中遇到的问题做一个详细说明。

环境

  • 开发工具: IntelliJ IDEA 2019.3.3
  • 编译工具: gradle-6.4-rc-4
  • 操作系统: windows 10
  • Spring版本:Spring5.3.0

编译

一、下载Spring源码

访问Spring官方源码地址 https://github.com/spring-projects/spring-framework.git,下载源码zip包到本地

二、下载和配置编译工具Gradle

1. 下载Gradle

访问Gradle官网 https://services.gradle.org/distributions/,选择gradle-6.4-rc-4-bin.zip(截止2020-05-03当前最新),下载到本地并解压

2. 配置Gradle系统环境变量

3. 验证Gradle

三、IntelliJ IDEA编译Spring源码

1. 导入Spring源码至IntelliJ IDEA

将之前下载好的Spring源码解压后导入到IDEA,依次点击File->New->Project from Existing Sources,选择源码包路径下的build.gradle文件完成源码导入

2. IntelliJ IDEA配置Gradle

依次打开File->Settings



3. 开始编译

在编译开始之前,我们先看看下载的官方源码里给出的导入IDEA的提示

![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9pLmxvbGkubmV0LzIwMjAvMDUvMDMvMW81RFJ0dnhCemVjZnlYLnBuZw?x-oss-process=image/format,png按照上面描述,因为上面导入我是按照第二步去做的。最后仅仅只需做第1条,预编译spring-oxm。进入项目路径,执行以下命令完成spring-oxm的预编译即可

 gradlew :spring-oxm:compileTestJava

完成了spring-oxm的预编译之后,就可以编译我们的代码了,一般由IDEA自动帮我们完成源码到projects的转换,也可以由我们手动import。



自此,编译的整个过程已经完成。下面我们要做的事就是添加自己的模块对已编译的项目模块进行验证测试,相信我验证会是一个有趣的过程。

测试

打开源码我们可以看到每个模块都对应的有单元测试,再相比较平时自己在开发时干的事情。再想到流行的敏捷开发模式中的TDD(测试驱动开发),没有测试就没有功能代码。不禁觉得其中的优秀是为了让我忘尘而叹。

扯回正题,不能让你们觉得我扯废话凑字数暴露没啥水平的真实情况。上面说到各个模块的单元测试我们可以测试编译项目是否有问题,但是后续学习在于模块之间的整合之上。所以我在此添加一个新的模块,这个模块模拟一个bean的创建和获取这么个过程。

1. 创建模块spring-demo

依次右击项目->New->Module

2. 添加测试模块代码

先预览下添加的代码结构吧,很简单是不?加上需要添加依赖的build.gradle共5个文件。



我这里贴出这5个文件的代码

@Configuration
@ComponentScan("com.fly4j.spring.context.**")
public class ContextConfig {
}
public interface IUserService {
}
@Service
@Scope("singleton")
public class UserServiceImpl implements IUserService {
public UserServiceImpl() {
System.out.println(this.getClass().getSimpleName() + " 构造函数执行...");
}
}
public class ContextApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
ContextConfig.class
);
IUserService bean = context.getBean(IUserService.class);
System.out.println(bean);
}
}
// build.gradle
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile(project(":spring-context"))
compile(project(":spring-instrument"))
}

相信以上代码机智的你一看就明白其意,其中build.gradle就只添加了spring-context和spring-instrument的依赖,spring-context模块里包含了bean工厂,可想而知,我这里生成bean和取出bean的测试案例是多么的依赖这个模块,另一个spring-instrument是spring-context模块编译需要的。

3. 测试

运行ContextApplication的main方法,其中会提示找不到CoroutinesUtils符号,这个问题解决我在下面一节的“问题一”进行了说明,我这里先放结果好了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-74slidVQ-1588949769544)(https://i.loli.net/2020/05/03/A3qyDnE4CKIxd17.png)]

如上可以看到从上下文注入bean和取出bean的过程,至此spring-context这个重要模块验证成功结束。

问题

1. 问题一

Error:(350, 51) java: 找不到符号
符号: 变量 CoroutinesUtils
位置: 类 org.springframework.core.ReactiveAdapterRegistry.CoroutinesRegistrar

解决: 依次File->Project Structure->Libraries->+->java->spring-core->kotlin-coroutines->build->libs->kotlin-coroutines-5.3.0-SNAPSHOT.jar



2. 问题二

Error:(26, 38) java: 找不到符号
符号: 类 InstrumentationSavingAgent
位置: 程序包 org.springframework.instrument

解决: 因为spring-context对spring-instrument有依赖,在build.gradle添加对spring-instrument的依赖即可。

结语

至此,Spring源码如何在IntelliJ IDEA如何编译这篇文章就废话完毕了。写这篇文章目的我希望把它作为Spring系列的开始,没有环境的学习就像你想抬一个没有边角的桌子无处施力。如果大家在编译时有什么问题欢迎指出。也可以联系我(微信号:WxHXR2015),大家相互学习,在当前环境下自己也是一个担心有今天没明天的菜比技术人。最后贴出我编译好的spring源码的地址,欢迎star。

https://github.com/haoxianrui/spring-framework.git

Spring源码学习01:IntelliJ IDEA2019.3编译Spring5.3.x源码的更多相关文章

  1. Spring源码解析 | 第一篇 :IntelliJ IDEA2019.3编译Spring5.3.x源码

    前言 工欲善其事必先利其器.学习和深读Spring源码一个重要的前提:编译源码到我们的本地环境.这样方便我们在本地环境添加注释.断点追踪.查看类或接口的继承关系等等,更加高效的学习Spring源码.个 ...

  2. 【iScroll源码学习01】准备阶段 - 叶小钗

    [iScroll源码学习01]准备阶段 - 叶小钗 时间 2013-12-29 18:41:00 博客园-原创精华区 原文  http://www.cnblogs.com/yexiaochai/p/3 ...

  3. Hadoop源码学习笔记之NameNode启动场景流程一:源码环境搭建和项目模块及NameNode结构简单介绍

    最近在跟着一个大佬学习Hadoop底层源码及架构等知识点,觉得有必要记录下来这个学习过程.想到了这个废弃已久的blog账号,决定重新开始更新. 主要分以下几步来进行源码学习: 一.搭建源码阅读环境二. ...

  4. 【requireJS源码学习01】了解整个requireJS的结构

    前言 现在工作中基本离不开requireJS这种模块管理工具了,之前一直在用,但是对其原理不甚熟悉,整两天我们来试着学习其源码,而后在探寻其背后的AMD思想吧 于是今天的目标是熟悉requireJS整 ...

  5. 【iScroll源码学习01】准备阶段

    前言 我们昨天初步了解了为什么会出现iScroll:[SPA]移动站点APP化研究之上中下页面的iScroll化(上),然后简单的写了一个demo来模拟iScroll,其中了解到了以下知识点: ① v ...

  6. VUE 源码学习01 源码入口

    VUE[version:2.4.1] Vue项目做了不少,最近在学习设计模式与Vue源码,记录一下自己的脚印!共勉!注:此处源码学习方式为先了解其大模块,从宏观再去到微观学习,以免一开始就研究细节然后 ...

  7. jQuery 源码学习 - 01 - 简洁的 $('...')

    首先贴上学习参考资料:[深入浅出jQuery]源码浅析--整体架构,备用地址:chokcoco/jQuery-. jQuery 库,js 开发的一个里程碑,它的出现,让网页开发者们告别荒蛮的上古时代, ...

  8. 【js】vue 2.5.1 源码学习 (十一) 模板编译compileToFunctions渲染函数

    大体思路(九) 本节内容: 1. compileToFunctions定位 1. compileToFunctions定位 ==> createCompiler = createCompiler ...

  9. 编译Spring5.2.0源码

    下载 spring-framework-5.2.0.RELEASE.zip https://github.com/spring-projects/spring-framework/releases 下 ...

随机推荐

  1. es搜索排序不正确

    沿用该文章里的数据https://www.cnblogs.com/MRLL/p/12691763.html 查询时发现,一模一样的name,但是相关度不一样 GET /z_test/doc/_sear ...

  2. 简单完成Excel导出

    Excel的导出只需要三步即可完成: 1,完成excel的工具类编写,直接复制即可 package cn.com.bcl.util; import java.util.List; import org ...

  3. dubbo(三):负载均衡实现解析

    dubbo作为分布式远程调用框架,要保证的点很多,比如:服务注册与发现.故障转移.高性能通信.负载均衡等等! 负载均衡的目的是为了特定场景下,能够将请求合理地平分到各服务实例上,以便发挥所有机器的叠加 ...

  4. 好玩的GeoGebra

    目前,在网站上看到好多大牛写的信号方面的笔记,有很多好玩的gif好玩又让人能明白其中的原理,工欲善其事必先利其器,在写我的博客方面先来学一个好玩的数学软件吧. GeoGebra官网如图 它是一个小巧的 ...

  5. Oracle NULL值

    NULL值,用来描述记录中没有定义内容的字段值.在Oracle中,判断某个条件的值时,返回值可能是TRUE.FALSE或UNKNOWN. 如果查询一个列的值是否等于20,而该列的值为NULL,那么就是 ...

  6. 一文回顾Reids五大对象(数据类型)

    Redis 是一个高性能的分布式内存型数据库,在国内外各大互联网公司中都有着广泛的使用,即使是一些非互联网公司中也有着非常重要的适用场景,所以对 Redis 的掌握也成为后端工程师必备的基础技能,在面 ...

  7. Problem C Careful Ascent

    数学问题. 在不经过shield时,竖直速度是1.所以时间就是y/1=y,,,,在经过shield时,时间为shield的数值长度*影响因素,然后总时间把他们加起来,最后再用水平方向的长度除以总时间, ...

  8. 数据挖掘入门系列教程(十)之k-means算法

    简介 这一次我们来讲一下比较轻松简单的数据挖掘的算法--K-Means算法.K-Means算法是一种无监督的聚类算法.什么叫无监督呢?就是对于训练集的数据,在训练的过程中,并没有告诉训练算法某一个数据 ...

  9. MySQL笔记总结-其他

    数据库相关概念 一.数据库的好处 1.可以持久化数据到本地 2.结构化查询 二.数据库的常见概念 ★ 1.DB:数据库,存储数据的容器 2.DBMS:数据库管理系统,又称为数据库软件或数据库产品,用于 ...

  10. php 常量的使用

    我们来看下直接的例子 <?php //定义常量 //常量不可被删除 //常量一旦被定义,就无法重新置换 //常量一旦定义,就不能对他第二次定义,否则会报错! define('MYCONSTANT ...