介绍
Spring‑Framework 核心上下文顶级接口,属于 Spring IOC 容器的门面接口 (Facade)。
接口总览
java
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver
EnvironmentCapable
获取环境配置对象Environment,读取配置文件、系统属性、环境变量。
外部配置抽象,容器与配置解耦,支持 profile、属性占位符。
ListableBeanFactory
可枚举 Bean 的 BeanFactory,可以获取全部 bean 名称、按类型获取 bean 列表。
批量 bean 查询能力 ,基础BeanFactory只能按名称单个获取。
HierarchicalBeanFactory
分层 BeanFactory,支持父子容器层级。
容器层级架构,SpringMVC 就是典型:父容器 Spring 根容器,子容器 MVC 容器,父子隔离 Bean
MessageSource
国际化消息解析。
i18n 能力,把国际化能力内置到容器,业务直接从上下文拿消息,不用自己维护资源文件。
ApplicationEventPublisher
事件发布器,发布 Spring 事件。
容器内置事件驱动,观察者模式,解耦启动、刷新、关闭等生命周期业务逻辑。
ResourcePatternResolver
资源加载解析,支持 classpath*:、file: 等通配符加载资源。
统一资源抽象,屏蔽磁盘、classpath、网络资源差异。
🔔架构核心设计思想:接口多继承,能力组合
原始
BeanFactory只是最底层 IOC 容器,只提供 Bean 实例获取。
ApplicationContext不修改原有 BeanFactory 接口,通过多继承把「配置、层级、国际化、事件、资源」多种能力组合叠加,变成一个功能完备的高级 IOC 容器门面。
👉门面模式 (Facade) :对外暴露ApplicationContext作为统一入口,内部实际委托给内部持有的DefaultListableBeanFactory完成真正 Bean 管理,外部应用几乎不会直接操作底层 BeanFactory。
注意:ApplicationContext只是接口,不做任何实现 ;真正实现类:AbstractApplicationContext抽象模板实现,再往下ClassPathXmlApplicationContext、AnnotationConfigApplicationContext。
源码解析
java
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
/**
* 获取当前上下文实例的唯一标识ID
* @return 上下文唯一id,允许返回null
*
* 架构用途:
* 1. 同一个JVM可以存在多个ApplicationContext实例(父子容器、多模块),用id区分;
* 2. 日志输出、监控埋点、多容器隔离识别;
* 3. 可由用户自定义设置,ConfigurableApplicationContext#setId()
*/
String getId();
/**
* 获取该上下文所属部署应用的应用名称
* @return 部署应用名称,默认返回空字符串
*
* 架构用途:
* 用于多应用部署场景,区分归属哪个应用;
* 一般SpringBoot会填充为spring.application.name,普通Spring项目默认为""
*/
String getApplicationName();
/**
* 获取上下文友好展示名称
* @return 用于打印日志的展示名称,绝对不为null
*
* 架构用途:
* 纯粹日志、调试输出,便于排查多容器问题;
* 例如输出:AnnotationConfigApplicationContext@2d209079
*/
String getDisplayName();
/**
* 获取上下文第一次加载完成的时间戳(毫秒)
* @return 容器初始化完成的毫秒时间戳
*
* 架构用途:
* 1. 统计容器启动耗时;
* 2. 判断容器什么时候完成refresh刷新;
* ⚠️注意:不是对象new的时间,是refresh()执行完成的时间点
*/
long getStartupDate();
/**
* 获取父上下文对象
* @return 返回父ApplicationContext,如果是根容器没有父容器则返回null
*
* 【父子容器核心】
* 1. 典型场景SpringMVC:Root WebApplicationContext(父) 、Servlet WebApplicationContext(子)
* 2. Bean查找规则:子容器找不到bean,会向上委托父容器查找;父容器看不到子容器Bean
* 3. 可以用来做模块隔离,公共Bean放父容器,模块私有Bean放子容器
*/
ApplicationContext getParent();
/**
* 暴露AutowireCapableBeanFactory能力
* @return 返回具备自动装配能力的BeanFactory
* @throws IllegalStateException 如果容器还没有refresh刷新,或者不支持该工厂抛出异常
*
* 🔴非常重要的方法,业务代码极少用,但是框架拓展高频!
*
* 背景:普通ApplicationContext门面,没有暴露「手动执行bean生命周期、依赖注入」的API。
* AutowireCapableBeanFactory能干什么:
* 1. 对new出来的外部对象(不在Spring容器管理的对象)执行依赖注入 @Autowired;
* 2. 手动执行bean的初始化方法、Aware回调、AOP代理创建;
*
* 使用场景举例:
* 1. Spring集成Quartz,quartz自己new Job对象,需要spring注入依赖;
* 2. 手动new领域对象,想要享受Spring自动装配;
*
* 重要提醒:
* 调用该方法前提:容器必须已经执行完refresh(),否则抛异常;
* ConfigurableApplicationContext#getBeanFactory()也可以拿到底层工厂,本方法是便捷封装。
*/
AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
架构层面深度拆解
BeanFactory vs ApplicationContext
BeanFactory:底层 IOC 容器,最小核心集合,只做 Bean 实例化获取,惰性初始化 bean。ApplicationContext:继承BeanFactory子接口,高级容器门面,默认立刻初始化所有单例 Bean,叠加配置、事件、国际化、资源、父子容器全套能力。
设计取舍:Spring 没有把所有方法塞到 BeanFactory,使用接口拆分,单一职责。底层 API 轻量,上层门面功能丰富。
2. 父子容器 Hierarchical 层级设计
getParent()体现容器层级架构:
- 子容器可以看到父容器 Bean,父看不到子容器;
- 适合拆分:公共组件、dao 层放在父容器;controller、web 相关放在子容器;
- SpringBoot 现在很少手动构建父子容器,但底层代码完整保留这套能力。
3. getAutowireCapableBeanFactory()的设计思考
为什么不直接把这个 API 放普通 BeanFactory?
AutowireCapableBeanFactory包含大量 bean 生命周期内部操作,属于框架内部 API,不希望普通业务开发随意调用 ,所以没有暴露在普通BeanFactory。只有通过
ApplicationContext主动获取,提示使用者:这是高级能力,谨慎使用。
4. 门面模式的实现细节
ApplicationContext接口本身不会实现 Bean 逻辑。
以AbstractApplicationContext举例:
内部持有一个真正的DefaultListableBeanFactory实例;ApplicationContext 所有继承来的 BeanFactory 接口方法,全部委托给内部这个 beanFactory 对象完成。
ApplicationContext = 装饰门面,真正干活的 BeanFactory 在内部持有。
5. 接口能力拆分的好处
- 最小依赖:如果你只需要资源加载,你可以只依赖
ResourcePatternResolver接口,不需要整个上下文; - 可替换实现:可以自定义实现 ApplicationContext 接口,替换容器实现;
- 接口职责单一,每个接口只负责一块能力,符合接口隔离原则 ISP。