★ BeanFactory 与 ApplicationContext 区别
结论先行:ApplicationContext 是 BeanFactory 的功能超集——它通过继承链间接实现 BeanFactory 的 getBean 等基础能力,并叠加了国际化(MessageSource)、事件发布(ApplicationEventPublisher)、资源加载(ResourcePatternResolver)、Environment 与自动注册 BeanPostProcessor 等企业级能力。一句话:BeanFactory 只管"Bean 的存取",ApplicationContext 管"Bean + 应用运行时";日常开发直接用 ApplicationContext(注解时代用 AnnotationConfigApplicationContext)。
一、继承关系速览
// ApplicationContext 同时具备以下能力(多接口)
public interface ApplicationContext extends EnvironmentCapable,
ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver { }
二、核心区别对比
| 对比项 | BeanFactory | ApplicationContext |
|---|---|---|
| 定位 | 最底层 IoC 容器接口 | BeanFactory 的企业级增强 |
| 单例实例化时机 | getBean 时才创建(懒加载) | 启动 refresh() 时预实例化全部单例(默认 eager) |
| BeanPostProcessor | 需手动 registerBeanPostProcessor | 启动时自动注册(AOP/@Autowired 能工作的前提) |
| 事件机制 | 无 | 内建事件发布/监听 |
| 国际化 | 无 | MessageSource(i18n) |
| 资源/环境 | 无 | ResourceLoader、Environment(profile、属性源) |
| 注解/扫描 | 无 | @ComponentScan 等由后置处理器完成 |
| 常用实现 | DefaultListableBeanFactory | AnnotationConfigApplicationContext、ClassPathXmlApplicationContext、WebApplicationContext |
| 场景 | 框架内部、内存极敏感 | 一切常规 Spring 应用 |
三、为什么 AOP / @Autowired 必须靠 ApplicationContext
- @Autowired 由 AutowiredAnnotationBeanPostProcessor 处理,AOP 由 AbstractAutoProxyCreator 处理,二者都是 BeanPostProcessor;
- BeanFactory 不会自动注册这些后置处理器,只有 ApplicationContext 在 refresh 时统一注册,所以脱离容器或只用裸 BeanFactory 时注解不生效。
// 二者都能 getBean,但能力差异很大
BeanFactory bf = new DefaultListableBeanFactory(); // 纯存取
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); // 全功能
Object bean = ctx.getBean("orderService");
ctx.publishEvent(new OrderCreatedEvent(1L)); // BeanFactory 做不到
常见追问 / 记忆点
- 追问 1:为什么单例 Bean 默认预实例化?答:尽早暴露配置/初始化错误(fail-fast),同时预热常用对象;懒加载可用 @Lazy。
- 追问 2:最常用的实现类?答:注解项目用 AnnotationConfigApplicationContext,XML 老项目用 ClassPathXmlApplicationContext,Web 环境是 WebApplicationContext。
- 记忆点:"BeanFactory 管 Bean,ApplicationContext 管 Bean + 应用(事件/资源/国际化),BeanPostProcessor 自动注册是关键差异"。