Spring源码怎么读?模块划分与面试高频追问的全景解析

发布时间:2026/10/8 10:45:42
Spring源码怎么读?模块划分与面试高频追问的全景解析 “看过源码吗说一下Spring有哪些模块”这道题我面试别人时问过很多次自己也被人问过无数次。说实话绝大多数候选人听到这个问题都会愣一下然后开始背“Spring由IOC容器、AOP、事务、MVC组成”这种教科书答案。这种回答不能说错但面试官听完基本不会有印象。为什么因为这道题真正想听的不是你能不能报出模块名字而是你有没有真正翻开过Spring的代码能不能从源码的组织方式反推出一个大型框架的设计思路。如果你正在准备Java面试或者想系统提升自己对Spring的理解这篇文章值得看完。我会从面试官的角度拆解这道题的考察意图把Spring的模块体系像地图一样给你铺开再给你一套可以直接用来回答的话术框架最后聊聊怎么真正开始读源码而不是停留在“看过”两个字上。1. 面试官为什么爱问“看过源码吗”1.1 考察的不是记忆力是学习习惯先说一个扎心的事实大部分人说自己“看过Spring源码”实际只是看过几篇“Spring IOC源码解析”的博客或者跟着视频断点调试过一两个方法然后记住了某个类名。这不算看过源码最多算“浏览过”。面试官问“看过源码吗”第一层想了解的是你遇到问题时会不会自己找答案。Spring Boot 报个错报错信息里明明带着类名和行号有没有人真的点进去看过大部分人的习惯是直接搜索解决方案复制粘贴报错消失就完事。这种习惯应付日常开发勉强够用但遇到线上诡异问题时没有底层理解就只能靠运气。所以“看过源码吗”这个问题实际上是在筛选候选人的学习深度。你说看过面试官就会接着问细节问到你对不上为止你说没看过面试官也不会直接判死刑但会看你有没有清晰的进阶规划。最怕的就是那种“看过但我说不清”的状态这比坦诚说“没深入看过”更减分。1.2 第二层考察模块体系认知这个问题里其实藏着一个陷阱“说一下Spring有哪些模块”。如果你从Spring Framework的官方文档角度回答应该列出几十个模块如果你从业务角度回答可能只记得IOC、AOP、MVC、事务。这两个答案的差距就是“阅读过源码”和“使用过框架”的差距。读过源码的人会知道Spring在构建时被拆成了独立的jar包每个jar包对应一个模块模块之间通过spring-core准确说是spring-core和spring-beans作为地基往上叠加。你甚至可以精确说出来spring-aop模块里有个ProxyFactoryspring-context模块里才有ApplicationContext接口spring-webmvc模块里才有DispatcherServlet。这种颗粒度的回答立刻就能和普通候选人拉开差距。1.3 第三层考察源码里体现的设计思想Spring的模块划分不是随意的它背后是一套完整的依赖管理原则。比如spring-core绝不允许依赖spring-web而spring-web可以依赖spring-core。这种单向依赖关系保证了框架的可扩展性和可测试性。如果你能顺着模块划分往下讲出这套设计约束面试官对你的评价会从“用过Spring”上升到“理解Spring”。这也是为什么这篇面试题值得单独拿出来写一篇完整解析——因为它问的既是一个知识点也是一个学习方向的启示。2. Spring模块全景从源码jar包的角度重新认识框架2.1 模块划分的底层逻辑打开Spring Framework的源码仓库根目录下的spring-*文件夹就是一个个模块。你可以直接去GitHub看spring-projects/spring-framework不用下载先看目录结构就能感受到模块化设计的力量。5.x版本Spring 5和6.x版本Spring 6的模块划分基本一致只是6.x基于Java 17并调整了部分模块内部细节。我把常见模块整理成一张表你面试前至少要把这张表刻在脑子里。模块名对应jar包核心职责关键类/接口Core Container核心容器spring-core / spring-beansIoC容器基础Bean定义加载、依赖注入核心BeanFactory、BeanDefinition、BeanPostProcessorContextspring-context在Core之上扩展出ApplicationContext并提供事件、国际化、资源加载等能力ApplicationContext、ApplicationEvent、MessageSourceAOPspring-aop面向切面编程实现基于代理的增强ProxyFactory、Aspect、AdvisorAspectsspring-aspects集成AspectJ提供更丰富的切点表达式支持Configurable、AspectJ的AnnotationBeanConfigurerAspectData Access / JDBCspring-jdbc简化JDBC开发统一异常体系JdbcTemplate、DataSourceUtilsORMspring-orm集成Hibernate/JPA/MyBatis等ORM框架HibernateTemplate、JpaTransactionManagerTransactionspring-tx声明式事务抽象提供统一事务管理接口PlatformTransactionManager、TransactionalWebspring-webWeb基础能力HTTP抽象、客户端等RestTemplate、HttpMessageConverterWeb MVCspring-webmvc基于Servlet的Web框架用于构建控制器和视图DispatcherServlet、Controller、HandlerMappingWeb Fluxspring-webflux响应式Web框架非阻塞Mono、Flux、WebClientTestspring-test集成测试支持Mock环境等SpringJUnit4ClassRunner、MockMvcIntegrationspring-jms / spring-jmx / spring-messaging等支持Java消息服务、JMX、消息协议等JmsTemplate、JmsListener这张表不需要全背但核心容器、Context、AOP、WebMVC、Transaction这五个模块的jar包名和关键类你必须脱口而出。因为面试官后面的追问百分之八十会落在这五个模块里。2.2 核心容器模块Spring一切功能的地基spring-core和spring-beans乾包是整个框架最底层的存在。你在读源码时一定会发现几乎所有其他模块都直接或间接依赖这两个模块。spring-core干的事很基础但无比重要提供Resource抽象即把文件、类路径、URL统一视为可加载的资源、ConversionService类型转换、Collections工具类、SpringUtils等。它的存在感最低但缺了它整个框架跑不起来。spring-beans才是IoC的真正起点。BeanFactory接口在这里定义DefaultListableBeanFactory是它的核心实现面试常考你必须知道。这个模块还包含了Bean定义信息模型BeanDefinition、Bean实例化阶段的BeanPostProcessor、Bean作用域等关键概念。如果你读过源码你会知道一个经典的调用链// 伪代码展示核心流程 XmlBeanDefinitionReader reader new XmlBeanDefinitionReader(beanFactory); reader.loadBeanDefinitions(spring.xml); beanFactory.preInstantiateSingletons(); // 触发单例Bean的创建这个三行流程就是IoC容器的入门钥匙。从BeanDefinition的注册到getBean()时按需实例化再到依赖注入这整条链路都发生在spring-beans模块内部。2.3 Context模块让容器变得“好用”spring-context模块是大多数开发者真正接触的入口。如果你用ApplicationContext而不是直接操作BeanFactory那你就在用这个模块。ApplicationContext接口继承自BeanFactory并增强了国际化的MessageSource、资源加载的ResourceLoader、事件发布的ApplicationEventPublisher等能力。可以说spring-context就是一套面向业务的完整容器框架。读源码时要注意AbstractApplicationContext的refresh()方法是Spring容器的生命周期总控方法。这个方法体很长但读一遍就能理解Spring启动时发生了什么创建BeanFactory、注册默认环境、执行BeanFactoryPostProcessor、注册BeanPostProcessor、初始化事件分发器、创建所有非懒加载单例Bean。网上那句经典的“Spring源码只要看懂refresh()就看懂了一半”说的就是spring-context模块里的这个方法。2.4 AOP与Aspects代理的黑魔法spring-aop模块是Spring实现面向切面编程的核心。这里的关键是理解Spring AOP使用动态代理而不是修改字节码。它运行时通过ProxyFactory生成代理对象把切面逻辑织入到目标方法调用前后。读源码时会看到两类代理如果目标类实现了接口Spring用JDK动态代理如果没有接口Spring用CGLIB生成子类代理。这个知识点在面试中几乎必问而且会以“Spring事务失效场景”之类的问题出现。spring-aspects模块则负责把AspectJ的注解如Aspect、Pointcut、Around解析成Spring AOP能理解的Advisor。很多人把Spring AOP和AspectJ混为一谈其实Spring AOP借用AspectJ的注解语法但运行时实现仍然是自己的代理机制。这部分读源码时不用深挖AspectJ编译器知道Spring只用了它的注解模型就行。2.5 数据访问与事务绕不开的Spring/MyBatis组合spring-jdbc模块最典型的价值是JdbcTemplate它把“连接管理、Statement创建、结果集映射、异常处理”这一整套样板代码都收拢起来。在MyBatis流行之前Spring官方主推的方案就是JdbcTemplate。spring-tx模块定义了统一的事务抽象。这里有两个概念必须分清PlatformTransactionManager事务管理器顶层接口它不关心你的事务是JDBC还是JPA还是别的只负责定义“获取事务、提交、回滚”的标准动作。TransactionDefinition事务的传播行为、隔离级别、超时时间等配置定义。读spring-tx源码时重点看AbstractPlatformTransactionManager的模板方法设计。SpringTransaction的提交和回滚过程被抽象成一个稳定模板而不同数据源的具体操作由子类实现。这种“模板方法模式”在框架设计里非常典型面试时你可以顺手点出来让面试官知道你读代码时想到了设计模式。另外现在做Java后端spring-boot-starter-jdbc和MyBatis基本是标配。虽然MyBatis本身不是Spring的模块但Spring通过mybatis-spring这个桥接模块把两者整合在一起。这个桥接模块里有一个核心类叫MapperFactoryBean它让每个Mapper接口都能被Spring管理和注入。读这部分源码时你会发现Spring对第三方集成的思路非常一致提供一个实现指定接口的FactoryBean让第三方组件以Bean的方式无缝接入。2.6 Web与MVC请求是怎么被处理的spring-web模块是Web开发的基础它提供了HTTP抽象、RestTemplate、HttpMessageConverter等通用能力本身不依赖Servlet容器的具体实现。spring-webmvc模块才是真正的MVC框架。面试中你不需要背每个类的源码但DispatcherServlet的处理链路要能流畅地说出来请求到达DispatcherServlet它通过HandlerMapping找到对应的HandlerExecutionChain。由HandlerAdapter执行处理器Controller方法。执行前经过一系列HandlerInterceptor的preHandle。处理器返回ModelAndView或直接返回数据再由HandlerAdapter统一处理。ViewResolver解析视图名渲染响应。这套流程几乎是Web后端面试的必问题。如果还想加深印象可以尝试读DispatcherServlet.doDispatch()方法不到100行就能看完核心分支但你能真正理解Spring MVC到底干了哪些活。2.7 测试与其他模块加分项spring-test模块在很多候选人眼里是个透明模块。其实这个模块里的SpringExtension、TestContextManager很有讲头。你如果自己看过源码就能回答出SpringBootTest是怎么把Spring容器和JUnit 5集成起来的这面试官会觉得你有广度。spring-messaging、spring-websocket、spring-jms这些模块属于特定场景才使用。参考价值在于你能说出“Spring除了常见的Web和IOC还提供了消息、WebSocket、JMS等集成模块”显示你对Spring生态级别的理解。3. 现场回答一套能过面试官耳朵的表述框架3.1 回答的分层逻辑这个问题回答不能只有一层。我建议你按“结论-架构-示例-细节”四步来组织语言。先把模块体系讲清楚然后挑一个你真正读过的细节深挖用深度带动广度。3.2 完整的回答示例下面这段是我一个字一个字帮你打磨的现场话术你可以根据自己的经验调整但骨架要保留“我系统看过Spring的源码但不敢说每个模块都精读。我先说模块划分Spring是一个模块化非常清晰的框架假如你去GitHub上看它的工程目录会发现顶层是按spring-core、spring-beans、spring-context、spring-aop、spring-tx、spring-jdbc、spring-webmvc、spring-webflux这样的jar包来拆分模块的。最底层的是spring-core和spring-beans它们定义了IoC容器的基础比如BeanFactory、BeanDefinition还有Resource、类型转换这些工具。往上走是spring-context也就是我们平时用的ApplicationContext所在模块。ApplicationContext继承了BeanFactory并扩展了事件、国际化、资源加载等功能。Spring启动时最重要的refresh()方法就在这个模块里。AOP和事务分别是spring-aop、spring-aspects和spring-tx模块。Spring AOP使用动态代理实现接口类用JDK代理没有接口的用CGLIB。事务模块把PlatformTransactionManager作为顶层抽象实际提交回滚用的是模板方法模式。Web层就是spring-web和spring-webmvcDispatcherServlet的doDispatch()方法处理整个请求链路。我刚才提到的这些模块里我自己实际读过的一个典型例子是BeanFactory的getBean()流程。从转换beanName、到从单例池singletonObjects里查缓存的实例再到如果缓存没有就进入doGetBean()根据BeanDefinition执行createBean()创建实例。这里面最有趣的就是三级缓存用三个Map解决了循环依赖这让我理解了Spring设计时对性能和功能的平衡。另外我还比较熟的还有Spring AOP创建代理的流程。当你标注了AspectSpring会通过AnnotationAwareAspectJAutoProxyCreator检测到Advisor然后对匹配到的bean生成代理对象。这块源码我建议不要只看结论自己用断点跑一遍会理解更深。”这段回答大概300多字涵盖了模块全景、源码细节、个人理解面试官听完基本可以确认你确实读过源码而不是背了概念。3.3 回答时千万别踩的坑回答时有两类常见错误代价很大。第一类是超范围卖弄。比如你明明只读过BeanFactory非要说“Spring事务的源码我也很熟”。面试官一旦追问“事务管理器如何决定回滚”你答不上来就会把前面的信任分全赔出去。不如诚实一点“事务这块我了解基本概念和接口但源码只读过commit和rollback的入口没有深入。”第二类是只讲概念不讲过程。很多人回答时会说“Spring核心模块有IOC、AOP、事务”但没有一句提到自己读到了哪个类、哪一行代码。这在面试官眼里和背诵没区别。想让回答有说服力必须带上具体的类名、方法名或调用链比如“我看到DefaultSingletonBeanRegistry里有三级缓存singletonObjects、earlySingletonObjects和singletonFactories”。4. 源码阅读实操从零开始的正确路线4.1 先定基调别直接翻Spring Boot我见过不少人一上来就打开SpringApplication.run()读了两天记了一堆启动流程面试时却发现问的根本不是这玩意儿。Spring Boot的源码是基于Spring Framework的自动装配和启动器它是一个“包装层”不是你理解IoC和AOP的核心。真正应该先读的是Spring Framework源码。建议直接下载源码或者通过Maven拉取spring-beans和spring-context的jar包配合Idea的反编译功能或者直接关联源码包。4.2 推荐阅读顺序按这个顺序来效率翻倍第一步理解BeanFactory和BeanDefinition写一个最简单的XML配置里面定义一个只有两个属性的Bean。用ClassPathXmlApplicationContext加载它然后断点进入refresh()找到getBean()调用。你需要在这一阶段搞清楚XML配置怎么变成BeanDefinitionBeanDefinition怎么注册进MapgetBean()时怎么根据BeanDefinition反射创建实例DefaultListableBeanFactory里面几个关键字段看一眼// DefaultListableBeanFactory 核心字段简化 private final MapString, BeanDefinition beanDefinitionMap new ConcurrentHashMap(256); private volatile ListString beanDefinitionNames new ArrayList(256);看到这个Map你就能理解“容器本质就是注册表”这句话。第二步深入单例创建与三级缓存创建单例Bean的代码集中在AbstractBeanFactory的doGetBean和DefaultSingletonBeanRegistry的getSingleton方法里。核心考点就是三级缓存singletonObjects一级缓存存放完全创建好的单例Bean。earlySingletonObjects二级缓存存放提前暴露的原始对象未填充属性。singletonFactories三级缓存存放可以生成早期对象的工厂。读到这里你会发现循环依赖的解决本质上不是靠什么黑魔法而是通过getEarlyBeanReference()提前暴露一个“半成品”给其他Bean引用。这个点值得你用笔自己画一张调用流程图画出来才算真懂。第三步读BeanPostProcessor这是Spring里威力最大的扩展点。BeanPostProcessor的两个方法postProcessBeforeInitialization和postProcessAfterInitialization分别在Bean初始化前后被调用。AOP就是在postProcessAfterInitialization阶段通过AbstractAutoProxyCreator给目标Bean生成代理的。沿着这条线你还能读到Autowired的依赖注入其实是由AutowiredAnnotationBeanPostProcessor来完成的这能让你从源码层面理解IOC和AOP是如何交织在一起的。第四步读AOP代理创建流程从AnnotationAwareAspectJAutoProxyCreator开始它会查找所有Advisor判断是否匹配当前Bean的切点匹配的话就创建代理。读到这里你自然能理解代理对象和目标对象的关系。第五步带着问题去翻事务不用从头看到尾。就带着几个问题去读Transactional是怎么被解析的TransactionInterceptor拦截到方法后做了什么事务是如何在AbstractPlatformTransactionManager里提交和回滚的把这三个函数读一遍事务源码就掌握了大半。4.3 高效源码阅读工具建议光靠眼睛看代码效率很低我把自己的工具链分享给你IDE反编译Idea打开jar包时选择“Attach Sources”或者直接使用FernFlower反编译器定位类很方便。Debug断点调试不用解释最直接的方式。关键点不是单步执行而是观察调用栈你会看到从Controller到Service到Mapper的全链路调用。画图流程图画清楚再继续推荐用draw.io或者白纸手绘理解速度比强行记忆代码快十倍。单元测试Spring源码仓库自带大量单元测试你可搜索spring-beans/src/test找到某个测试类打断点运行一次秒懂某个功能的使用方式。5. 高频追问与避坑指南5.1 追问一“Spring三级缓存是怎么回事”这个问题在热词里排得极其靠前可以说已经成了Spring面试的明星问题。就算面试官不直接问源码也会问循环依赖。首先记住一个定义Spring通过三级缓存解决的是“单例Bean之间的循环依赖”而且解决的是“setter注入”或“字段注入”的循环依赖构造器注入的循环依赖不仅解决不了而且一启动就会报错。关键在于理解三级缓存分包放什么一级缓存singletonObjects是IOC容器里所有完整的单例Bean。二级缓存earlySingletonObjects是“提前上架”的半成品对象。这个对象已经通过构造器创建出来但还未完成属性填充。三级缓存singletonFactories是解决循环依赖的核心它保存的不是Bean实例而是一个ObjectFactory这个工厂可以在需要时生成该Bean的原始实例或代理实例。当A和B互相依赖时流程是这样的创建A调用createBeanInstance实例化A此时A是半成品。把A的ObjectFactory放入三级缓存。填充A的属性发现依赖B于是去创建B。创建B过程中填充属性发现依赖A于是到三级缓存找到A的工厂调用getEarlyBeanReference得到A的早期引用放入二级缓存并把三级缓存中的工厂移除。B完成创建放入一级缓存。A继续填充其他属性最终完成初始化放入一级缓存。你回答时如果能顺手说出“三级缓存中存放的是ObjectFactory而不是对象本身”这一句话就能体现你读过源码因为很多讲博客的人根本不提supplier和getEarlyBeanReference的差别。5.2 追问二“Spring中有哪些设计模式”这个问题经常紧随模块问题而来。准备几个例子就可以工厂模式BeanFactory是抽象工厂FactoryBean是工厂Bean大家最容易混淆。BeanFactory是容器FactoryBean是创建复杂对象的工厂接口。模板方法模式JdbcTemplate把固定流程写在模板里业务变化的部分通过回调传入AbstractPlatformTransactionManager也大量使用模板方法。代理模式AOP本身就是代理模式的典型应用。观察者模式Spring事件机制。ApplicationEventPublisher发布事件EventListener订阅事件。适配器模式HandlerAdapter让DispatcherServlet可以执行各种类型的处理器。面试官问你设计模式不是为了考基础知识而是想看你能不能把理论和框架联系起来。每个模式举一个Spring里的具体类回答质量就到位了。5.3 追问三“MyBatis和Spring是怎么整合的”这个追问在现在几乎是必选项因为Spring Boot MyBatis已经成为后端标配。你可以从mybatis-spring模块的源码出发回答MyBatis的SqlSessionFactory可以通过FactoryBean方式注册为Spring的BeanMapperFactoryBean让每个Mapper接口变成一个Spring管理的单例Bean。当调用Mapper接口方法时实际是通过SqlSessionTemplate执行SQL。Spring对MyBatis的事务管理则通过SpringManagedTransaction接管了MyBatis原先的JDBC事务逻辑。回答时记住一个核心点MyBatis并不依赖Spring容器但Spring通过一套适配层把MyBatis纳入自己的生命周期管理。这种第三方集成思路在Spring生态里反复出现。5.4 实际面试中让你尴尬的三种“死法”我把这些年当面试官听到的“送命回答”也列出来帮你避雷“我看过源码就是看不懂所以只记住了类名。”——这种话就不要说了等于宣告自己是背答案。“Spring模块有IOC、AOP、MVC、Bean、事务就这些了。”——只说了概念没说模块名也没提关键类听起来像没用过Spring。“源码在idea里我经常在里面搜索。”——这句话等于没说。要看关键类、找调用链、分析设计思路才叫读过。6. 从这道题延伸出来的自检清单面试结束之后问一下自己这几个问题。如果都能流畅回答这道题就真正过关了BeanFactory和ApplicationContext的区别到底是什么ClassPathXmlApplicationContext的继承链上分别是哪个类开始的refresh()前几行代码干了什么AOP的代理对象是何时被放入容器的Transactional失效的一个常见原因是什么背后的源码依据是什么我在读Spring源码这件事上踩过很多坑。最开始的错误是找一堆解析博客一篇篇看下去看完就忘。后来我改变策略不追求读懂所有地方只把一个最小闭环读透。比如从ClassPathXmlApplicationContext到getBean(user)再到打印出这个User对象为止这一小段链路里的类、方法、缓存结构全部弄明白比泛泛翻完全部源码有用得多。如果你正在准备面试我特别建议你把这篇文章当作一张地图而不是答案本身。地图告诉你模块在哪里、源码里有什么但真正值钱的是你亲自用断点跑一遍getBean()亲眼看一次三级缓存是怎么工作的。等到面试官问你“看过源码吗”的时候你会发现自己根本不需要背张嘴就能讲出那些类名和方法名因为你是真的见过它们。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询