• BeanFactory 可以理解为含有 bean 集合的工厂类。BeanFactory 包含了种 bean 的定义,以便在接收到客户端请求时将对应的 bean 实例化。

  • BeanFactory 还能在实例化对象的时生成协作类之间的关系。此举将 bean 自身与 bean 客户端的配置中解放出来。BeanFactory 还包含了 bean 生命周期的控制,调用客户端的初始化方法(initialization methods)和销毁方法(destruction methods)。

  • 从表面上看,ApplicationContext 如同 BeanFactory 一样具有 bean 定义、bean 关联关系的设置,根据请求分发 bean 的功能。但 ApplicationContext 在此基础上还提供了其他的功能:

    • 提供了支持国际化的文本消息
    • 统一的资源文件读取方式
    • 已在监听器中注册的 bean 的事件

功能清单之外,两者最本质的差异只有一条:bean 的实例化时机——懒加载 vs 启动时预实例化。这条差异派生了启动性能、错误暴露时机、内存占用等所有工程区别。本文以此为主线展开。

核心差异:实例化时机

  • BeanFactory:getBean 时才实例化(懒加载)。容器启动只解析注册 bean 定义(BeanDefinition),不创建实例
  • ApplicationContext:refresh 阶段就对所有非懒加载单例预实例化(finishBeanFactoryInitialization 中 preInstantiateSingletons)

派生影响:

维度 BeanFactory ApplicationContext
启动速度 快(不建实例) 慢(预建全部单例)
配置错误暴露 第一次 getBean 才爆 启动即爆(fail-fast,生产友好)
内存 按需 启动即占满单例
AOP/后处理器 需手动注册 自动应用 BeanPostProcessor
事件/国际化/资源加载 无 内建(ApplicationEventPublisher/MessageSource/ResourceLoader)
Web 集成 无 WebApplicationContext 族

接口谱系:ApplicationContext 是超集

ApplicationContext 继承链:ApplicationContext extends ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver...。即它首先是完整的 BeanFactory,再叠加企业级设施。所以”区别”准确说是”基础容器 vs 全功能容器”,而非两种平行实现。

为什么生产永远用 ApplicationContext

  • fail-fast:Bean 定义错误、依赖缺失、循环依赖(构造器级)在启动时暴露,而不是凌晨三点第一次被调用时
  • 后处理器自动生效:@Autowired 注入、@PostConstruct、AOP 代理都依赖 BeanPostProcessor 的注册与应用——裸 BeanFactory 下这些注解”不工作”,是新手最常见的困惑来源
  • 事件机制:ApplicationEvent 发布/监听是框架与业务解耦的基础设施(如监听 ContextRefreshedEvent 做启动后初始化)
  • Web 必需:Servlet 容器集成(ContextLoaderListener)只认 WebApplicationContext

BeanFactory 的今天的位置:内部 SPI 与极端受限环境(如嵌入式/内存敏感场景手动控制实例化),以及源码阅读时理解容器核心的入口(DefaultListableBeanFactory 才是真正干活的类,ApplicationContext 是把功能组装起来的外壳)。

一个验证性实验

DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.registerBeanDefinition("svc", new RootBeanDefinition(Service.class));
// 此刻 Service 尚未实例化;bf.getBean("svc") 才创建,且 @Autowired 字段为 null(无后处理器)

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
// 启动即实例化全部单例,@Autowired/@PostConstruct/AOP 全部生效

两行对比即全部区别的实证:时机 + 后处理器。

面试答法

一句话版:BeanFactory 是最基础的 IoC 容器 SPI,懒加载、功能最小;ApplicationContext 在其上预实例化单例并集成事件、国际化、资源加载与后处理器自动应用,是应用开发的唯一选择;两者差异的根是实例化时机,其余都是派生。