Skip to content

Spring 核心原理概览 ​

你写的 @Service 里没有一个 new,依赖却都能用;你写的 @Transactional 方法里没有一行事务代码,抛出 RuntimeException 却能自动回滚。前者靠 IoC 容器替你管理对象与依赖,后者靠 AOP 替你包一层代理。Spring 的上层能力大多长在这两套机制上,本专题就从它们讲起。

1. 为什么会有 Spring ​

Spring 不是凭空设计出来的,它是对一个具体历史问题的回应。2002 年前后,Java 企业开发的主流方案是 J2EE 规范,EJB(Enterprise JavaBeans)是其中标准化的企业级组件模型。但 EJB 2.x 的代价很高:

EJB 2.x 的负担具体表现
组件膨胀典型 EJB 2.x 开发模式下,一个业务 Bean 要写 Home 接口、Local/Remote 接口、实现类和 ejb-jar.xml,一个类配多个文件
强制容器Bean 必须跑在 EJB 容器里,离开容器无法运行,写单元测试要先搭起容器环境
持久化笨重实体 Bean 用 CMP 做对象关系映射,表达能力弱,复杂查询很难写
侵入性强Bean 必须实现 EJB 规定的接口、抛规定的异常,业务代码和框架深度耦合

Rod Johnson 在 2002 年出版的《Expert One-on-One J2EE Design and Development》里系统论证了一件事:没有 EJB,企业应用照样能写好。他给的替代品是一套朴素的组合,普通 POJO 加依赖注入来组装对象,AOP 来织入横切逻辑。

2003 年这套代码以 Spring 之名开源(Apache 2.0 许可),2004 年 3 月发布 1.0。它的核心目标,是把对象从 EJB 容器里解放出来,回到普通 POJO。组装交给 IoC,横切交给 AOP,本专题就围绕这两块地基展开。

2. 版本演进 ​

从 2004 年的 1.0 到 2022 年的 6.0,Spring Framework 每次大版本升级都在回应一个具体的问题。下表也纳入了 Spring Boot,它是建立在 Framework 之上的另一条产品线:

版本年份主要变化
1.02004轻量容器落地,IoC 和 AOP 成型,核心容器、数据访问、Web 三层骨架搭起来
2.0 / 2.52006 / 2007XML 配置越堆越厚,2.5 引入 @Autowired、@Component,装配开始从 XML 挪进代码
3.02009@Configuration + @Bean 提供了一种不用 XML 的 Java Config 装配方式
4.02013全面支持 Java 8 特性,补上 @RestController、WebSocket 等 Web 能力
Spring Boot 1.02014Spring 自身的配置又成了负担,Boot 用自动配置加约定优于配置,大幅削减启动配置
5.02017引入基于 Reactive Streams 的 WebFlux,为 I/O 密集场景提供非阻塞的响应式栈
6.02022基线升到 JDK 17,命名空间从 javax 切到 jakarta(Jakarta EE 9+),并推进 AOT 与原生镜像支持

装配方式从 XML 走向注解、Java Config,再到 Boot 的自动配置;运行模型从传统容器式应用,走向 WebFlux 的响应式处理和 AOT、原生镜像。这些机制彼此并不替代,注解与 XML、WebFlux 与 Spring MVC 至今并存,各自解决的是不同阶段最突出的痛点。

3. 框架版图 ​

Spring Framework 由多个模块组成,核心容器只是其中一条主线。理解这条主线,可以沿着三层自下而上地读,分层的收益是只想用轻量容器的人不必背上全部依赖:

模块层职责关键类型
spring-core底层基础设施与通用工具(资源访问、类型转换、排序),不含 Bean 定义Resource、Ordered
spring-beans定义 Bean 的元数据与创建工厂,IoC 容器的底座BeanDefinition、BeanFactory
spring-context在 beans 之上叠加事件、国际化、注解配置等应用上下文能力ApplicationContext、MessageSource

图中箭头即依赖方向,只允许上层依赖下层。由此能推出一个常被问到的结论:BeanFactory 定义在 spring-beans,ApplicationContext 定义在 spring-context,后者在前者之上叠加了应用上下文能力,详见 IoC 容器。AOP、事务、Web 这些能力,都建立在同一套 Bean 装配之上:

4. 知识地图 ​

本专题的六个模块连成一条主线。容器先学会创建 Bean(IoC),再看单个 Bean 从创建到销毁的完整流程(生命周期),依赖在这个流程里注入(DI),相互依赖时用三级缓存解开(循环依赖),横切逻辑靠代理增强(AOP),最后按条件决定哪些 Bean 生效(条件装配)。

  • IoC 容器:入口,先解决「谁创建对象」。容器能创建 Bean,后面的注入、代理才有对象可操作。
  • Bean 生命周期:单个 Bean 从 new 到销毁的完整流程,是注入、循环依赖、代理共同依赖的骨架。
  • 依赖注入:解决「依赖怎么进去」。构造器注入发生在实例化阶段,Setter 和字段注入发生在属性填充阶段,它不是生命周期里的单独一步。
  • AOP:解决「横切逻辑怎么复用」,代理对象通常在生命周期「初始化」阶段生成。
  • 循环依赖:注入的极端情况,A 依赖 B、B 又依赖 A。Spring 用三级缓存提前暴露早期引用,解开部分单例循环依赖,三级缓存同时和 AOP 的早期代理有关。
  • 条件装配:解决「哪些 Bean 该生效」,按条件决定 Bean 是否注册,是 Spring Boot 自动配置的基础。

Released under the MIT License.