上篇我们定好了路线,这篇是后面所有源码追踪的地基:没有能断点的环境,读源码就是纸上谈兵。目标只有一个——让你在本机把 spring-framework 跑起来,并写一个最小 Demo 断进去。

一、为什么要搭调试环境

看博客、截图、PDF,当时看懂,三天就忘。真正吃透源码的方式只有一种:能断点、能单步、能看调用栈

本篇做完,你应该能:

  • 在本机导入并编译 spring-framework 源码;
  • 写一段最小的 Spring 启动代码;
  • refresh() 上打断点,一路 Step Into 跟下去。

二、环境前置

依赖 建议版本 说明
JDK 8(或 11) Spring 5.3 对 JDK 8 最稳,避免 JDK 17 的模块系统坑
Git 任意新版 用于拉源码
IntelliJ IDEA 2020.3+ 社区版足够
内存 8G+ Gradle 构建吃内存
Gradle 不需要装 仓库自带 gradle wrapper(./gradlew),直接用

关键提醒:不要自己另外装 Gradle。仓库根目录的 gradlew / gradlew.bat 会自动下载匹配版本,自己装错版本反而报错。

三、第一步:拉取源码

强烈建议基于稳定 tag,别直接拉 master(master 可能含未发布的破坏性改动)。

# 方式一:GitHub(慢可挂代理)
git clone -b 5.3.x https://github.com/spring-projects/spring-framework.git

# 方式二:国内 Gitee 镜像(速度快)
git clone -b 5.3.x https://gitee.com/mirrors/Spring-Framework.git

cd spring-framework
git checkout v5.3.39   # 选一个具体 release tag,结果更可复现

5.3.x 是 5.3 的维护分支;若想完全可复现,直接 checkout 具体 tag(如 v5.3.39)。

四、第二步:预编译关键模块(很多人卡在这)

Spring 官方导入指南要求先编译 spring-oxm 的测试代码——它用 AspectJ 生成部分类,不预先编译,IDEA 导入后会报一堆找不到符号。

# Mac / Linux
./gradlew :spring-oxm:compileTestJava

# Windows
gradlew.bat :spring-oxm:compileTestJava

这一步很快,几分钟内结束。

五、第三步:导入 IDEA

  1. Open or Import → 选择 spring-framework 根目录下的 build.gradle(注意是 Gradle 不是 Maven,别选 pom.xml);
  2. 勾选 Use auto-import(自动导入依赖变化);
  3. 等待 IDEA 下载依赖 + 建立索引,首次较慢(10~30 分钟,看网速);
  4. 导入完成后,项目结构里能看到 spring-corespring-beansspring-context 等模块。

若 IDEA 提示 Kotlin 未配置,去 Plugins 装 Kotlin 插件,或执行 ./gradlew :spring-core:compileKotlin

六、第四步:写最小调试 Demo

不要改框架代码。最省事的方案是借用框架自带的 test 源集,它天然依赖所有 Spring 模块。

spring-context 模块的 src/test/java 下新建包 com.demo,写三个类:

// AppConfig.java
@Configuration
@ComponentScan("com.demo")
public class AppConfig {
}
// DemoBean.java
@Component
public class DemoBean {
    public void hello() {
        System.out.println("hello spring");
    }
}
// Main.java
public class Main {
    public static void main(String[] args) {
        // 在这里打断电,跟进 refresh()
        AnnotationConfigApplicationContext ctx =
                new AnnotationConfigApplicationContext(AppConfig.class);
        ctx.getBean(DemoBean.class).hello();
    }
}

如果你的 IDEA 不允许在 test 源集里跑 main,也可以新建一个独立 Gradle 子模块,在 build.gradleimplementation(project(":spring-context")) 后照写即可。

七、第五步:断点调试

  1. org.springframework.context.support.AbstractApplicationContext.refresh() 第一行打断电;
  2. 右键 Main.main()Debug
  3. 程序停在断点后,用 IDEA 的 Call Stack 窗口看调用链,Step Into(F7)逐行跟进;
  4. 这几个方法是后面几篇的重点,建议现在就逐个点进去扫一眼:
    • obtainFreshBeanFactory():加载并注册 BeanDefinition;
    • invokeBeanFactoryPostProcessors():执行 BeanFactoryPostProcessor;
    • registerBeanPostProcessors():注册 BeanPostProcessor;
    • finishBeanFactoryInitialization():实例化所有非懒加载单例 Bean。

能跑到这里并看懂 refresh() 在干嘛,本篇目标就达成了。

八、常见问题排查

  • Kotlin not configured:装 Kotlin 插件,或 ./gradlew :spring-core:compileKotlin
  • 构建 OOM / 卡死:给 IDEA 的 Gradle、Compiler 加大堆,例如 -Xmx2g
  • JDK 版本报错:确认 Project SDK = JDK 8,且 gradle.propertiesorg.gradle.java.home 指向 JDK 8;
  • 索引一直不结束:耐心等;或 File → Invalidate Caches / Restart
  • 断点进不去:确认跑的是源码模块里的 main,而不是你引入的外部 spring jar 包。

九、小结

到这一步,你已经能在本地断点调试 Spring 源码——这是后续每一篇「源码追踪」的前提,我写的每一步你都能自己复现。

下一篇我们正式进入 IoC 容器,从最基础也最容易混淆的问题讲起:BeanFactory 与 ApplicationContext 到底差在哪


如果这篇帮你少踩了坑,欢迎收藏 + 关注。下篇见。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐