Spring 容器深度解析:从 BeanFactory 到 ApplicationContext 的体系与实践
Spring 容器是 IOC(控制反转)思想的具体实现,核心职责是管理 Bean 的生命周期(创建、装配、销毁)与依赖关系,是 Spring 框架的 “心脏”。Spring 提供了两类核心容器:BeanFactory(基础容器)和 ApplicationContext(高级容器),二者在功能、初始化策略和适用场景上存在显著差异。从 “容器体系→核心实现→关键区别→Bean 定义元数据” 四个维度,彻底拆解 Spring 容器的工作机制。
Spring 容器体系总览
Spring 容器基于 “分层设计”,从基础到高级形成完整体系,核心接口与实现类的关系如下:

核心设计思路:BeanFactory 定义基础规范,ApplicationContext 在其之上扩展高级功能,满足不同场景需求(轻量级 vs 企业级)。
基础容器:BeanFactory 详解
BeanFactory 是 Spring 容器的顶层接口,定义了 IOC 容器的最小功能集 ——“获取 Bean、判断 Bean 状态”,是 Spring 框架内部使用的基础容器(面向框架基础设施)。
1. BeanFactory 核心接口与方法
1 | public interface BeanFactory { |
关键方法解析:
FACTORY_BEAN_PREFIX = "&":特殊前缀,用于获取FactoryBean本身(而非其生成的对象)。例如:getBean("userFactory"):获取userFactory这个FactoryBean生成的User对象;getBean("&userFactory"):获取userFactory这个FactoryBean实例本身。
getBean重载:支持多种获取方式,按类型获取(getBean(Class<T>))是最常用的,避免强转,更安全。- 单例 / 原型判断:
isSingleton和isPrototype对应 Bean 的scope配置(默认单例)。
2. BeanFactory 的核心子类
BeanFactory 接口本身不实现具体逻辑,其功能通过三个核心子类扩展:
| 子类接口 | 核心职责 | 典型实现类 |
|---|---|---|
| ListableBeanFactory | 支持批量获取 Bean 定义(解决 BeanFactory 只能单个获取的局限) | DefaultListableBeanFactory |
| HierarchicalBeanFactory | 支持父子容器层级(父容器的 Bean 可被子容器访问,反之不行) | DefaultListableBeanFactory |
| AutowireCapableBeanFactory | 支持Bean 自动装配(如 @Autowired)和手动创建 Bean(容器外对象纳入管理) |
DefaultListableBeanFactory |
经典实现:XmlBeanFactory(已过时)
XmlBeanFactory 是 BeanFactory 的经典实现,从 XML 配置文件加载 Bean 定义,但 Spring 3.1 后已过时,推荐使用 DefaultListableBeanFactory 配合 XmlBeanDefinitionReader:
1 | // 过时用法(不推荐) |
3. BeanFactory 的核心特性
- 延迟加载:容器初始化时不创建 Bean,仅在调用
getBean()时才实例化 Bean 并装配依赖; - 轻量级:仅提供基础 Bean 管理功能,内存占用低,适合资源敏感场景(如嵌入式设备、移动端);
- 手动注册处理器:使用
BeanPostProcessor(Bean 后置处理器)或BeanFactoryPostProcessor(Bean 工厂后置处理器)时,需手动调用addBeanPostProcessor()注册; - 面向框架内部:主要用于 Spring 框架自身(如早期 Spring 集成),开发者很少直接使用。
高级容器:ApplicationContext 详解
ApplicationContext 是 BeanFactory 的增强版,继承了 BeanFactory 的所有功能,并扩展了 “国际化、事件传播、资源加载” 等企业级特性,是开发者最常用的容器(面向应用开发者)。
1. ApplicationContext 的接口继承关系
ApplicationContext 之所以强大,是因为它继承了多个核心接口,整合了多维度能力:
1 | public interface ApplicationContext extends |
继承接口的核心能力:
EnvironmentCapable:管理环境变量(如spring.profiles.active区分开发 / 生产环境);MessageSource:支持多语言(如getMessage("user.name", null, Locale.CHINA)获取中文提示);ApplicationEventPublisher:发布事件(如publishEvent(new UserRegisteredEvent(user))),监听者(@EventListener)接收并处理;ResourcePatternResolver:灵活加载资源(如getResources("classpath*:com/example/mapper/*.xml")批量加载 Mapper XML)。
2. ApplicationContext 的核心实现类
ApplicationContext 是接口,其具体逻辑由子类实现,常用实现类按 “配置方式” 和 “运行环境” 分类:
(1)XML 配置型容器(传统方式)
| 实现类 | 核心特点 | 适用场景 |
|---|---|---|
| ClassPathXmlApplicationContext | 从类路径加载 XML 配置文件(如 src/main/resources/application.xml) |
非 Web 应用(如桌面应用、单元测试) |
| FileSystemXmlApplicationContext | 从文件系统路径加载 XML 配置(如 D:/config/application.xml) |
需指定绝对路径的场景 |
| XmlWebApplicationContext | 从Web 应用根目录加载 XML 配置(如 WEB-INF/applicationContext.xml) |
传统 Web 应用(如 SSH 架构) |
使用示例(ClassPathXmlApplicationContext):
1 | // 1. 创建容器并加载配置(refresh=true 表示初始化时立即创建单例 Bean) |
关键源码解析(ClassPathXmlApplicationContext 构造方法):
1 | public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) { |
refresh():ConfigurableApplicationContext接口的核心方法,是容器初始化的 “总开关”,完成 “Bean 定义解析→Bean 实例化→依赖注入→事件发布” 等全流程(后续章节详解)。
(2)注解配置型容器(现代方式)
AnnotationConfigApplicationContext:从注解类加载配置(如 @Configuration、@ComponentScan),是 Spring Boot 之前的主流注解容器。
使用示例:
1 | // 1. 配置类(替代 XML) |
(3)Web 专用容器
WebApplicationContext:专为 Web 应用设计,扩展了 ApplicationContext,提供 getServletContext() 方法获取 Servlet 上下文,其实现类 XmlWebApplicationContext 和 AnnotationConfigWebApplicationContext 分别对应 XML 和注解配置。
在 Spring MVC 中,DispatcherServlet 会初始化一个 WebApplicationContext(称为 “Servlet 容器”),与全局的 WebApplicationContext(称为 “Root 容器”)形成父子关系:
- Root 容器:管理 Service、Dao 层 Bean;
- Servlet 容器:管理 Controller 层 Bean,可访问 Root 容器的 Bean。
3. ApplicationContext 的核心特性
- 立即初始化:容器调用
refresh()时,一次性创建所有单例 Bean(默认scope="singleton"),启动时即可发现配置错误(如依赖缺失); - 自动注册处理器:
BeanPostProcessor(如AutowiredAnnotationBeanPostProcessor)和BeanFactoryPostProcessor(如PropertySourcesPlaceholderConfigurer)会被自动扫描并注册,无需手动操作; - 企业级特性:内置国际化、事件、资源加载能力,无需额外配置;
- 面向开发者:API 更友好(如按类型获取 Bean、自动装配),是绝大多数应用的首选容器。
BeanFactory 与 ApplicationContext 的核心区别
两者都是 Spring 容器的实现,但定位和能力差异显著,是面试高频考点,具体区别如下:
| 对比维度 | BeanFactory | ApplicationContext |
|---|---|---|
| 初始化策略 | 延迟加载(getBean() 时才创建 Bean) |
立即加载(refresh() 时创建所有单例 Bean) |
| 功能范围 | 基础 Bean 管理(获取、判断状态) | 基础管理 + 国际化 / 事件 / 资源加载 / 环境配置等 |
| 处理器注册 | 需手动调用 addBeanPostProcessor() |
自动扫描并注册(如 @Autowired 处理器) |
| 错误检测 | 启动时无错误检测,使用时才暴露问题 | 启动时检测配置错误(如依赖缺失、Bean 类型不匹配) |
| 内存占用 | 低(仅加载 Bean 定义,不创建实例) | 高(创建所有单例 Bean,占用内存) |
| API 友好性 | 接口设计偏底层(需强转、手动处理) | API 更友好(按类型获取、自动装配) |
| 适用场景 | 资源敏感场景(嵌入式设备、移动端) | 企业级应用(Web 应用、微服务) |
| 典型用户 | Spring 框架内部 | 应用开发者 |
一句话总结:BeanFactory 是 “轻量级基础设施”,ApplicationContext 是 “企业级应用容器”,除非有特殊资源限制,否则优先使用 ApplicationContext。
BeanDefinition:Bean 的 “元数据定义”
Spring 容器管理 Bean 的核心是 BeanDefinition—— 它抽象了 Bean 的 “定义信息”,是容器创建 Bean 的 “蓝图”。容器首先解析配置(XML / 注解)生成 BeanDefinition,再根据 BeanDefinition 实例化 Bean。
1. BeanDefinition 的核心作用
- 存储 Bean 的元数据:描述 Bean 的类名、作用域、依赖、初始化方法、销毁方法等;
- 解耦配置与创建:配置文件 / 注解仅负责定义 BeanDefinition,Bean 的创建由容器根据 BeanDefinition 统一处理;
- 统一管理 Bean 生命周期:容器根据 BeanDefinition 中的
initMethod、destroyMethod等配置,调用 Bean 的初始化和销毁方法。
2. BeanDefinition 的核心属性
BeanDefinition 接口定义了 Bean 的核心配置,常用属性如下:
1 | public interface BeanDefinition { |
3. BeanDefinition 的实现类
BeanDefinition 有三个主要实现类,对应不同场景:
| 实现类 | 核心特点 | 适用场景 |
|---|---|---|
| RootBeanDefinition | 最完整的 BeanDefinition,支持所有属性,是默认实现 | 绝大多数场景(如 @Bean、XML <bean>) |
| ChildBeanDefinition | 需依赖父 BeanDefinition,继承父的配置(已过时,被 GenericBeanDefinition 替代) | 已弃用,不推荐使用 |
| GenericBeanDefinition | 通用 BeanDefinition,支持父子依赖,更灵活,替代 ChildBeanDefinition | 动态注册 Bean(如编程式创建 Bean) |
4. BeanDefinition 的生命周期
BeanDefinition 从创建到使用的流程如下:
- 解析配置:容器通过
XmlBeanDefinitionReader(XML)或ConfigurationClassBeanDefinitionReader(注解)解析配置,生成 BeanDefinition; - 注册定义:将 BeanDefinition 注册到
BeanDefinitionRegistry(如DefaultListableBeanFactory),key 为 Bean 名称; - 处理增强:
BeanFactoryPostProcessor对 BeanDefinition 进行修改(如替换占位符${user.name}为实际值); - 实例化 Bean:容器根据 BeanDefinition 的类名、构造方法、依赖等信息,创建 Bean 实例并装配依赖;
- 销毁定义:容器关闭时,BeanDefinition 随容器一起销毁(无单独生命周期管理)。
总结:Spring 容器的选择与最佳实践
1. 容器选择原则
- 优先使用 ApplicationContext:企业级应用、Web 应用、微服务等场景,推荐
AnnotationConfigApplicationContext(注解)或 Spring Boot 自动配置的ApplicationContext; - 仅在特殊场景使用 BeanFactory:资源敏感场景(如嵌入式设备)、内存受限环境,使用
DefaultListableBeanFactory。
2. 最佳实践
- 注解配置替代 XML:使用
@Configuration+@ComponentScan+@Bean替代 XML,代码更简洁,类型更安全; - 理解 refresh () 方法:
refresh()是容器初始化的核心,包含 12 个步骤(如obtainFreshBeanFactory()加载 BeanDefinition、finishBeanFactoryInitialization()实例化单例 Bean),是排查容器启动问题的关键; - 避免滥用 BeanFactory:不要为了 “节省内存” 而使用 BeanFactory,现代应用内存充足,ApplicationContext 的错误检测和高级特性更有价值;
- 动态注册 Bean:通过
BeanDefinitionRegistry编程式注册 BeanDefinition(如registry.registerBeanDefinition("user", beanDefinition)),适用于动态扩展场景
spring容器
实现方式
spring中提供了各式各样的IOC容器的实现供用户选择和使用,使用什么样的容器取决于用户的需要
BeanFactory 该接口是最简单的容器,最顶层的接口类。提供了基本的DI支持。最常用的BeanFactory实现是XmlBeanFactory类,根据XML文件中的定义加载bean,从XML文件读取配置元数据并用它去创建一个完全配置的系统或应用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32public interface BeanFactory {
// 可以使用&来得到FactoryBean本身,用于区分用FactoryBean产生的对象和FactoryBean本身,
// 如使用myJndiObject获取到的是FactoryBean产生的对象,使用&myJndiObject可以获取到对应的FactoryBean对象
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}其有三个子类:
- ListableBeanFactory 表示这些Bean是可列表的
- HierarchicalBeanFactory 表示这些Bean是有继承关系的
- AutowireCapableBeanFactory 定义这些Bean的自动装配规则
ApplicationContext应用上下文 基于BeanFactory之上构建,属于高级容器,提供面向应用的服务,并继承了资源ResourcePatternResolver,消息MessageSource,事件ApplicationEventPublisher,环境EnvironmentCapable,工厂五种能力常见的实现方式
1
2
3
4// 实现MessageSource接口,可以支持不同的信息员,支持国际化
// 实现ApplicationEventPublisher,支持了事件机制
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver
ApplicationContext是一个接口,大部分的方法实现由AbstractApplicationContext实现
ClassPathXmlApplicationContext 继承了AbstractXmlApplicationContext抽象类,从类路径下的XML配置文件中加载上下文定义,把应用上下文定义文件当做资源
1
2
3
4
5
6
7
8
9
10
11
12
13ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
// this(new String[] {configLocation}, true, null);
// refresh为true,parent为null
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh(); // 触发了IOC容器的初始化
}
}FileSystemXmlApplicationContext 读取文件系统下的XML配置文件并加载上下文定义
XmlWebApplicationContext 读取Web应用下的XML配置文件并装载上下文
AnnotationConfigApplicationContext: 注解方式
ConfigurableApplicationContext扩展于ApplicationContext接口,新增了两个主要的方法,refresh()和close(),让ApplicationContext具有启动、刷新和关闭上下文的能力
WebApplicationContext专门为WEB应用准备的,允许从相对于WEB根目录的路径中初始化上下文
BeanFactory和ApplicationContext的区别
BeanFactory可以认为是bean集合的工厂类,包含了各种bean的定义,以便在接收到客户端请求时将对应的bean实例化,是spring最底层的接口,提供了最简单的容器的功能,包含了bean生命周期的控制,调用初始化方法和销毁方法,其采取的是延迟加载,第一次getBean时才会初始化
ApplicationContext继承了BeanFactory并进行了扩展,在初始化上下文时就实例化所有单例的bean,提供了支持国际化的文本消息MessageSource、统一的资源文件读取方式(扩展了ResourceLoader)、消息发送、事件机制(ApplicationEvent和ApplicationListener)等
BeanFactory采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。
BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。
BeanFactory主要是面对与 spring 框架的基础设施,面对 spring 自己。而 ApplicationContext 主要面对与 spring 使用的开发者。基本都会使用 ApplicationContext 并非 BeanFactory 。
BeanDefinition
spring通过BeanDefinition来管理基于spring的应用中的各种对象以及它们之间的相互依赖关系。BeanDefinition抽象了对Bean的定义,是让容器起作用的主要数据类型