0%

spring容器

Spring 容器深度解析:从 BeanFactory 到 ApplicationContext 的体系与实践

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

Spring 容器体系总览

Spring 容器基于 “分层设计”,从基础到高级形成完整体系,核心接口与实现类的关系如下:

spring容器

核心设计思路:BeanFactory 定义基础规范,ApplicationContext 在其之上扩展高级功能,满足不同场景需求(轻量级 vs 企业级)。

基础容器:BeanFactory 详解

BeanFactory 是 Spring 容器的顶层接口,定义了 IOC 容器的最小功能集 ——“获取 Bean、判断 Bean 状态”,是 Spring 框架内部使用的基础容器(面向框架基础设施)。

1. BeanFactory 核心接口与方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public interface BeanFactory {
// 关键常量:区分 FactoryBean 本身与它生成的对象(前缀 "&")
String FACTORY_BEAN_PREFIX = "&";

// 1. 获取 Bean(核心方法,支持按名称、类型、带参数构造)
Object getBean(String name) throws BeansException; // 按名称获取(返回 Object,需强转)
<T> T getBean(String name, Class<T> requiredType) throws BeansException; // 按名称+类型(无需强转)
Object getBean(String name, Object... args) throws BeansException; // 带构造参数(创建原型 Bean 时用)
<T> T getBean(Class<T> requiredType) throws BeansException; // 按类型获取(推荐,更类型安全)
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException; // 按类型+构造参数

// 2. 判断 Bean 状态
boolean containsBean(String name); // 容器中是否存在该名称的 Bean
boolean isSingleton(String name) throws NoSuchBeanDefinitionException; // 是否为单例(默认)
boolean isPrototype(String name) throws NoSuchBeanDefinitionException; // 是否为原型(每次 getBean 新建)
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException; // Bean 类型是否匹配
Class<?> getType(String name) throws NoSuchBeanDefinitionException; // 获取 Bean 的类型
String[] getAliases(String name); // 获取 Bean 的别名(一个 Bean 可多个别名)
}
关键方法解析:
  • FACTORY_BEAN_PREFIX = "&":特殊前缀,用于获取FactoryBean本身(而非其生成的对象)。例如:
    • getBean("userFactory"):获取 userFactory 这个 FactoryBean 生成的 User 对象;
    • getBean("&userFactory"):获取 userFactory 这个 FactoryBean 实例本身。
  • getBean 重载:支持多种获取方式,按类型获取(getBean(Class<T>))是最常用的,避免强转,更安全。
  • 单例 / 原型判断isSingletonisPrototype 对应 Bean 的 scope 配置(默认单例)。

2. BeanFactory 的核心子类

BeanFactory 接口本身不实现具体逻辑,其功能通过三个核心子类扩展:

子类接口 核心职责 典型实现类
ListableBeanFactory 支持批量获取 Bean 定义(解决 BeanFactory 只能单个获取的局限) DefaultListableBeanFactory
HierarchicalBeanFactory 支持父子容器层级(父容器的 Bean 可被子容器访问,反之不行) DefaultListableBeanFactory
AutowireCapableBeanFactory 支持Bean 自动装配(如 @Autowired)和手动创建 Bean(容器外对象纳入管理) DefaultListableBeanFactory
经典实现:XmlBeanFactory(已过时)

XmlBeanFactoryBeanFactory 的经典实现,从 XML 配置文件加载 Bean 定义,但 Spring 3.1 后已过时,推荐使用 DefaultListableBeanFactory 配合 XmlBeanDefinitionReader

1
2
3
4
5
6
7
8
9
10
11
// 过时用法(不推荐)
Resource resource = new ClassPathResource("application.xml");
BeanFactory factory = new XmlBeanFactory(resource);

// 现代用法(推荐)
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new ClassPathResource("application.xml"));

// 使用容器获取 Bean
User user = factory.getBean(User.class);

3. BeanFactory 的核心特性

  • 延迟加载:容器初始化时不创建 Bean,仅在调用 getBean() 时才实例化 Bean 并装配依赖;
  • 轻量级:仅提供基础 Bean 管理功能,内存占用低,适合资源敏感场景(如嵌入式设备、移动端);
  • 手动注册处理器:使用 BeanPostProcessor(Bean 后置处理器)或 BeanFactoryPostProcessor(Bean 工厂后置处理器)时,需手动调用 addBeanPostProcessor() 注册;
  • 面向框架内部:主要用于 Spring 框架自身(如早期 Spring 集成),开发者很少直接使用。

高级容器:ApplicationContext 详解

ApplicationContextBeanFactory增强版,继承了 BeanFactory 的所有功能,并扩展了 “国际化、事件传播、资源加载” 等企业级特性,是开发者最常用的容器(面向应用开发者)。

1. ApplicationContext 的接口继承关系

ApplicationContext 之所以强大,是因为它继承了多个核心接口,整合了多维度能力:

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface ApplicationContext extends 
EnvironmentCapable, // 1. 环境配置(如 profiles、属性配置)
ListableBeanFactory, // 2. 批量获取 Bean 定义(继承自 BeanFactory 子类)
HierarchicalBeanFactory, // 3. 父子容器层级(继承自 BeanFactory 子类)
MessageSource, // 4. 国际化消息支持(多语言)
ApplicationEventPublisher, // 5. 事件发布与监听(解耦组件通信)
ResourcePatternResolver // 6. 资源加载(支持通配符,如 classpath*:/*.xml)
{
// 新增:获取父容器
ApplicationContext getParent();
// 新增:获取环境配置(如 system.properties、application.properties)
Environment getEnvironment();
}
继承接口的核心能力:
  1. EnvironmentCapable:管理环境变量(如 spring.profiles.active 区分开发 / 生产环境);
  2. MessageSource:支持多语言(如 getMessage("user.name", null, Locale.CHINA) 获取中文提示);
  3. ApplicationEventPublisher:发布事件(如 publishEvent(new UserRegisteredEvent(user))),监听者(@EventListener)接收并处理;
  4. 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
2
3
4
5
6
7
8
9
// 1. 创建容器并加载配置(refresh=true 表示初始化时立即创建单例 Bean)
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");

// 2. 获取 Bean(支持按类型或名称)
UserService userService = context.getBean(UserService.class);
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);

// 3. 关闭容器(需强转为 ConfigurableApplicationContext)
((ConfigurableApplicationContext) context).close();

关键源码解析(ClassPathXmlApplicationContext 构造方法)

1
2
3
4
5
6
7
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) {
super(parent); // 设置父容器(可选)
setConfigLocations(configLocations); // 保存 XML 配置路径
if (refresh) {
refresh(); // 核心:触发容器初始化(创建单例 Bean、装配依赖)
}
}
  • refresh()ConfigurableApplicationContext 接口的核心方法,是容器初始化的 “总开关”,完成 “Bean 定义解析→Bean 实例化→依赖注入→事件发布” 等全流程(后续章节详解)。
(2)注解配置型容器(现代方式)

AnnotationConfigApplicationContext:从注解类加载配置(如 @Configuration@ComponentScan),是 Spring Boot 之前的主流注解容器。

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 1. 配置类(替代 XML)
@Configuration
@ComponentScan("com.example") // 扫描组件(@Component、@Service、@Controller 等)
public class AppConfig {
// 手动注册 Bean(替代 XML 中的 <bean> 标签)
@Bean
public UserMapper userMapper() {
return new UserMapper();
}
}

// 2. 创建容器并加载配置
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

// 3. 获取 Bean
UserService userService = context.getBean(UserService.class);
(3)Web 专用容器

WebApplicationContext:专为 Web 应用设计,扩展了 ApplicationContext,提供 getServletContext() 方法获取 Servlet 上下文,其实现类 XmlWebApplicationContextAnnotationConfigWebApplicationContext 分别对应 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 中的 initMethoddestroyMethod 等配置,调用 Bean 的初始化和销毁方法。

2. BeanDefinition 的核心属性

BeanDefinition 接口定义了 Bean 的核心配置,常用属性如下:

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
32
33
public interface BeanDefinition {
// 1. Bean 的基本信息
String getBeanClassName(); // Bean 的全限定类名(如 com.example.UserService)
void setBeanClassName(String beanClassName);

// 2. 作用域(singleton/prototype/request/session)
String getScope();
void setScope(String scope);
boolean isSingleton(); // 是否单例(默认 true)
boolean isPrototype(); // 是否原型(默认 false)

// 3. 延迟初始化(仅单例有效)
boolean isLazyInit(); // 是否延迟初始化(默认 false,即立即初始化)
void setLazyInit(boolean lazyInit);

// 4. 依赖关系
String[] getDependsOn(); // 依赖的 Bean 名称(初始化当前 Bean 前先初始化依赖)
void setDependsOn(String... dependsOn);

// 5. 自动装配相关
boolean isAutowireCandidate(); // 是否参与自动装配(默认 true)
void setAutowireCandidate(boolean autowireCandidate);

// 6. 初始化与销毁方法
String getInitMethodName(); // 初始化方法名(如 init())
void setInitMethodName(String initMethodName);
String getDestroyMethodName(); // 销毁方法名(如 destroy())
void setDestroyMethodName(String destroyMethodName);

// 7. Bean 的角色(框架内部 Bean 还是应用 Bean)
int getRole();
void setRole(int role);
}

3. BeanDefinition 的实现类

BeanDefinition 有三个主要实现类,对应不同场景:

实现类 核心特点 适用场景
RootBeanDefinition 最完整的 BeanDefinition,支持所有属性,是默认实现 绝大多数场景(如 @Bean、XML <bean>
ChildBeanDefinition 需依赖父 BeanDefinition,继承父的配置(已过时,被 GenericBeanDefinition 替代) 已弃用,不推荐使用
GenericBeanDefinition 通用 BeanDefinition,支持父子依赖,更灵活,替代 ChildBeanDefinition 动态注册 Bean(如编程式创建 Bean)

4. BeanDefinition 的生命周期

BeanDefinition 从创建到使用的流程如下:

  1. 解析配置:容器通过 XmlBeanDefinitionReader(XML)或 ConfigurationClassBeanDefinitionReader(注解)解析配置,生成 BeanDefinition;
  2. 注册定义:将 BeanDefinition 注册到 BeanDefinitionRegistry(如 DefaultListableBeanFactory),key 为 Bean 名称;
  3. 处理增强BeanFactoryPostProcessor 对 BeanDefinition 进行修改(如替换占位符 ${user.name} 为实际值);
  4. 实例化 Bean:容器根据 BeanDefinition 的类名、构造方法、依赖等信息,创建 Bean 实例并装配依赖;
  5. 销毁定义:容器关闭时,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
    32
    public 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
    13
    ApplicationContext  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的定义,是让容器起作用的主要数据类型

欢迎关注我的其它发布渠道