Spring IoC 容器入门:BeanFactory vs ApplicationContext 区别与启动方式详解(2026)
TL;DR
- 场景:Spring 初学者搭建企业级项目时,常混淆 IoC 容器顶层接口与具体实现,不知道该选 BeanFactory 还是 ApplicationContext,以及 Java / Web 环境下的容器启动方式
- 结论:ApplicationContext 是 BeanFactory 的子接口,功能更完整(国际化、事件、AOP、资源加载),是企业开发首选;Java 环境用
ClassPathXmlApplicationContext/AnnotationConfigApplicationContext,Web 环境用ContextLoaderListener - 产出:1 张接口继承图 + 1 张功能对比表 + 2 段 web.xml 配置(XML 方式与配置类方式)
版本矩阵
| 功能 | 状态 | 说明 |
|---|---|---|
| BeanFactory 顶层接口定义 | ✅ 已验证 | org.springframework.beans.factory.BeanFactory 是 Spring IoC 容器最顶层接口 |
| ApplicationContext 子接口 | ✅ 已验证 | 继承自 BeanFactory,提供企业级扩展能力 |
| ClassPathXmlApplicationContext | ✅ 已验证 | 从类路径加载 XML 配置,JavaSE 环境常用 |
| FileSystemXmlApplicationContext | ✅ 已验证 | 从磁盘路径加载 XML 配置文件 |
| AnnotationConfigApplicationContext | ✅ 已验证 | 基于 Java 配置类启动 Spring 容器 |
| ContextLoaderListener | ✅ 已验证 | Web 环境启动 Spring 容器的标准监听器 |
| Spring 5.1.12.RELEASE 版本 | ✅ 已验证 | 5.1.x 稳定线版本,2019 年末发布,5.1.13 为 2020-01-14 最终维护版 |
IoC 基础
BeanFactory 和 ApplicationContext 区别
BeanFactory 是 Spring 框架中 IoC 容器的顶层接口,定义了 IoC 容器最基础的功能规范,例如 Bean 的获取、管理和依赖注入等。
ApplicationContext 是 BeanFactory 的子接口,因此它具备 BeanFactory 的全部能力。同时,ApplicationContext 在此基础上扩展了更多企业级开发常用功能,例如国际化、资源访问、事件发布、AOP 集成等。
简单理解:
BeanFactory 更偏底层,是 Spring IoC 容器的基础接口;ApplicationContext 更偏应用层,是实际开发中更常用的高级容器接口。
BeanFactory
- Spring IoC 容器的核心基础接口。
- 提供最基本的 Bean 管理能力。
- 默认采用延迟初始化,也就是在真正获取 Bean 时才创建对象。
- 更轻量,适合资源受限或底层框架扩展场景。
- 常见实现类:DefaultListableBeanFactory。
ApplicationContext
- BeanFactory 的子接口,功能更完整。
- 容器启动时通常会预先创建单例 Bean。
- 支持国际化、事件发布、资源加载、AOP 等高级功能。
- 更适合企业级应用开发。
- 常见实现类:ClassPathXmlApplicationContext、FileSystemXmlApplicationContext、AnnotationConfigApplicationContext 等。
BeanFactory 场景
BeanFactory 通常用于比较底层或资源受限的场景。
例如:
- 框架底层扩展。
- 测试环境。
- 对容器功能要求较少的简单场景。
- 需要尽量延迟创建 Bean 的场景。
在日常业务开发中,一般不会直接使用 BeanFactory。
ApplicationContext 场景
ApplicationContext 是 Spring 应用中最常用的 IoC 容器。
它适用于大多数企业级项目,能够支持:
- XML 配置。
- Java 配置类。
- 注解扫描。
- 国际化。
- 事件监听。
- AOP。
- Web 环境集成。
因此,在实际开发中,通常优先使用 ApplicationContext。
项目准备
拷贝项目
这里我们将上一节的项目拷贝一份,后续内容会在原有项目基础上继续调整。
这样做的好处是可以保留上一节的代码,同时避免本节改动影响之前的示例。
添加依赖
在上一节依赖的基础上,继续加入下面这些 Spring 相关依赖:
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.12.RELEASE</version>
</dependency>
这些依赖中:
- spring-context:提供 ApplicationContext、注解配置、资源加载等核心能力。
- spring-web:提供 Web 环境下启动 Spring 容器的支持。
- javax.annotation-api:提供 @PostConstruct、@PreDestroy 等注解。
- spring-aop 和 aspectjweaver:用于后续 AOP 相关功能。
- spring-jdbc 和 spring-tx:用于后续数据库操作和事务控制。
对应截图如下所示:
启动 IoC 容器
Spring IoC 容器可以在 Java 环境中启动,也可以在 Web 环境中启动。不同环境下,启动方式略有区别。
Java 环境
在普通 Java 程序中,常见的容器启动方式有以下几种:
- ClassPathXmlApplicationContext:从类路径下加载 XML 配置文件,常用于学习和传统 XML 项目。
- FileSystemXmlApplicationContext:从磁盘路径加载 XML 配置文件。
- AnnotationConfigApplicationContext:基于 Java 配置类启动 Spring 容器,常用于纯注解开发。
例如,如果使用 XML 配置文件,可以通过 ClassPathXmlApplicationContext 启动容器;如果使用配置类,则可以通过 AnnotationConfigApplicationContext 启动容器。
Web 环境
在 Web 项目中,Spring 容器通常不是由 main 方法手动启动,而是交给 Web 容器启动。
常见做法是在 web.xml 中配置 ContextLoaderListener。Web 项目启动时,监听器会自动创建 Spring IoC 容器。
XML 方式
如果使用 XML 配置方式启动 Spring 容器,可以修改 webapp/WEB-INF 下的 web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
上面配置中,ContextLoaderListener 会在 Web 项目启动时初始化 Spring 容器。
如果没有额外指定配置文件位置,Spring 默认会去查找 /WEB-INF/applicationContext.xml。
对应的截图如下所示:
配置类 方式
如果项目使用 Java 配置类,也可以通过 web.xml 指定容器类型和配置类位置:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>wzk.SpringConfig</param-value>
</context-param>
<!--使⽤监听器启动Spring的IOC容器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
这里需要注意两个参数:
- contextClass:指定使用 AnnotationConfigWebApplicationContext,也就是基于注解和配置类的 Web 容器。
- contextConfigLocation:指定 Spring 配置类的全限定类名,这里是
wzk.SpringConfig。
项目启动时,ContextLoaderListener 会读取这些配置,并根据指定的配置类创建 Spring IoC 容器。
对应的截图如下所示:
错误速查卡
| 症状 | 根因 | 定位 | 修复 |
|---|---|---|---|
启动报错 FileNotFoundException: /WEB-INF/applicationContext.xml | Web 环境下只配了 ContextLoaderListener,未指定配置文件位置,Spring 走默认路径 | 检查 web.xml 是否缺少 contextConfigLocation 参数 | 在 <context-param> 中显式指定 applicationContext.xml 路径,或改用配置类方式 |
启动报错 ClassNotFoundException: AnnotationConfigWebApplicationContext | web.xml 中 contextClass 指定了注解容器,但 pom.xml 缺少 spring-web 依赖 | 检查 pom.xml 中是否引入 spring-web | 加入 org.springframework:spring-web:5.1.12.RELEASE 依赖 |
Bean 在获取时才报错 NoSuchBeanDefinitionException | 使用 BeanFactory 但未注册 Bean,或包扫描路径配置错误 | 检查 beans.xml 的 <context:component-scan> 或 @ComponentScan 注解路径 | 修正扫描包路径,确保目标类在扫描范围内 |
@PostConstruct / @PreDestroy 注解不生效 | 缺少 javax.annotation-api 依赖,或被 Spring 的 CommonAnnotationBeanPostProcessor 排除 | 检查 pom.xml 是否引入 javax.annotation-api 1.3.2 | 添加 javax.annotation:javax.annotation-api:1.3.2 依赖 |
| 容器启动后单例 Bean 已被提前创建,影响启动速度 | 默认走 ApplicationContext 的预加载行为 | 确认容器类型,BeanFactory 才是延迟加载 | 若必须延迟加载,显式使用 DefaultListableBeanFactory |
| Spring 5.1.12.RELEASE 报 CVE 安全漏洞 | 该版本已是 5.1.x 旧版本线,5.1.13 为最终维护版,5.1.x 已 EOL | 查看 pom.xml 中的 spring-* 版本号 | 升级到 Spring 5.3.x 或 6.x(配合 Spring Boot 2.7+ / 3.x) |
作者:武子康的个人博客