前言
BeanFactory 和 ApplicationContext 是 Spring IoC 容器的兩大核心接口,雖然都負責 Bean 的實例化、配裝與生命週期管理,但在功能豐富度、適用場景、啟動機制等方面存在本質差異。本文從源碼架構、核心功能、性能特徵、選型指南四個維度深度解析。
一、繼承體系與核心定位
1. 接口繼承關係圖
BeanFactory (核心接口)
↑
ListableBeanFactory (可列舉 Bean)
↑
HierarchicalBeanFactory (父子容器)
↑
ConfigurableBeanFactory (可配置:單例/原型、類加載器、屬性編輯器)
↑
AutowireCapableBeanFactory (自動裝配能力)
↑
--------------------------------------------------
↑
ApplicationContext (企業級應用上下文)
↑ 繼承並擴展
├─ EnvironmentCapable (環境抽象:profiles、properties)
├─ ListableBeanFactory
├─ HierarchicalBeanFactory
├─ MessageSource (國際化消息)
├─ ApplicationEventPublisher (事件發布)
├─ ResourcePatternResolver (資源模式解析:classpath*:)
└─ Lifecycle (生命週期管理:start/stop)
2. 核心定位差異
| 維度 | BeanFactory | ApplicationContext |
| 定位 | IoC 容器最小化核心 | 面向企業級應用的豐富容器 |
| 設計初衷 | 提供基礎的 Bean 管理能力 | 在 BeanFactory 基礎上整合企業級功能 |
| 啟動模式 | 延遲加載(按需實例化) | 預實例化(啟動時創建所有 singleton) |
| 資源訪問 | 僅支援 Resource 接口 | 支援 ResourcePatternResolver (Ant 路徑匹配) |
| 國際化 | 不支援 | 內建 MessageSource 體系 |
| 事件機制 | 無 | 完整的 ApplicationEvent 體系 |
| AOP 整合 | 需手動配置 | 無縫整合,支援 @AspectJ、Schema-based |
| Web 支援 | 無 | WebApplicationContext 提供 ServletContext 感知 |
二、三大 ApplicationContext 實現類詳解
1. ClassPathXmlApplicationContext
// 從類路徑載入單個或多個配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{
"datasource.xml", "service.xml", "mvc.xml"
});
// 支援通配符
ApplicationContext ctx = new ClassPathXmlApplicationContext("config/*-context.xml");
- 適用場景:獨立應用、單元測試、批處理任務
- 資源解析:ClassPathResource,僅限類路徑下資源
- 啟動特點:掃描 classpath,合併多文件,構建 BeanDefinitionMap
2. FileSystemXmlApplicationContext
// 從文件系統絕對/相對路徑載入
ApplicationContext ctx = new FileSystemXmlApplicationContext("/opt/config/app-context.xml");
ApplicationContext ctx = new FileSystemXmlApplicationContext("file:./conf/spring.xml");
// 相對路徑基於當前工作目錄 (user.dir)
- 適用場景:外部化配置、多實例部署共享配置文件、Docker 掛載配置
- 資源解析:FileSystemResource,支援文件系統任意路徑
- 注意:路徑變更需重啟應用,不支援熱加載(除非配合 Spring Cloud Config)
3. XmlWebApplicationContext
// Web 環境專用,由 ContextLoaderListener/DispatcherServlet 自動創建
// 無需手動實例化,通過 web.xml 配置 contextConfigLocation
// 內部實現關鍵點:
// 1. 繼承 AbstractRefreshableWebApplicationContext
// 2. 持有 ServletContext 引用
// 3. 實現 ThemeSource、ServletContextAware
// 4. 支援 ServletContext 相對路徑:/WEB-INF/applicationContext.xml
- 核心優勢:感知 Web 環境,可訪問 ServletContext、Session、Request 作用域
- 作用域擴展:request、session、application、websocket(僅 Web 容器有效)
- 啟動流程:ContextLoaderListener → root WebApplicationContext → DispatcherServlet → child WebApplicationContext
4. 註解驅動實現類(現代主流)
| 實現類 | 配置方式 | 適用場景 |
| AnnotationConfigApplicationContext | @Configuration + @Bean | 獨立應用、測試、Java Config 純註解項目 |
| AnnotationConfigWebApplicationContext | @Configuration + @EnableWebMvc | Spring MVC 純註解配置、Spring Boot 內嵌容器 |
| GenericApplicationContext | 手動註冊 BeanDefinition | 動態構建容器、框架整合、測試 Mock |
三、啟動流程核心差異:Lazy vs Eager
1. BeanFactory 延遲加載機制
// 僅創建 BeanFactory,不實例化任何 Bean
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions("beans.xml");
// 首次 getBean() 時才觸發實例化
UserService service = (UserService) factory.getBean("userService"); // 此處才創建對象
- 優點:啟動極快,記憶體佔用低,適合資源受限環境
- 缺點:運行時才發現配置錯誤(類不存在、循環依賴、屬性缺失),首次請求延遲高
- 源碼關鍵:DefaultListableBeanFactory.preInstantiateSingletons() 不會 自動調用
2. ApplicationContext 預實例化機制
// refresh() 過程中自動調用 finishBeanFactoryInitialization()
@Override
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 1. 初始化轉換服務
beanFactory.setConversionService(new DefaultConversionService());
// 2. 註冊內嵌值解析器
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
// 3. 初始化 LoadTimeWeaver (AOP)
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String name : weaverAwareNames) {
getBean(name);
}
// 4. 核心:預實例化所有非懶加載的 singleton Bean
beanFactory.preInstantiateSingletons(); // 關鍵差異點
}
3. preInstantiateSingletons() 深度解析
@Override
public void preInstantiateSingletons() {
// 遍歷所有 BeanDefinition
for (String beanName : beanDefinitionNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 條件:非抽象、單例、非懶加載
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// FactoryBean 特殊處理
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof SmartFactoryBean && ((SmartFactoryBean<?>) bean).isEagerInit()) {
getBean(beanName); // 觸發實例化
}
} else {
getBean(beanName); // 普通 Bean 直接實例化
}
}
}
}
4. 性能對比實測數據(參考值)
| 指標 | BeanFactory (XML 100 Bean) | ApplicationContext (XML 100 Bean) |
| 啟動時間 | ~15ms | ~120ms |
| 首次 getBean 耗時 | ~5ms (含實例化) | ~0.1ms (已預創建) |
| 記憶體佔用 (啟動後) | ~8MB | ~25MB |
| 配置錯誤發現時間 | 運行時 (首次調用) | 啟動階段 (fail-fast) |
四、企業級功能深度對比
1. 國際化 (i18n) 支援
// ApplicationContext 內建
MessageSource messageSource = context.getBean(MessageSource.class);
String msg = messageSource.getMessage("user.login.success", null, Locale.CHINESE);
// 配置示例
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list><value>i18n/messages</value></list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
// BeanFactory 需手動註冊 MessageSource Bean,無統一獲取入口
2. 事件發布與監聽
// 1. 發布事件
context.publishEvent(new UserRegisteredEvent(this, userId));
// 2. 監聽器實現
@Component
public class UserEventListener implements ApplicationListener<UserRegisteredEvent> {
@Override
public void onApplicationEvent(UserRegisteredEvent event) {
// 異步發送歡迎郵件、初始化用戶配置
}
}
// 3. 註解式監聽 (Spring 4.2+)
@EventListener
public void handleUserRegistered(UserRegisteredEvent event) { ... }
@EventListener(condition = "#event.userId > 1000")
public void handleVipUser(UserRegisteredEvent event) { ... }
// BeanFactory:無 ApplicationEventPublisher 接口,需自建事件總線
3. 資源加載能力
// ApplicationContext 實現 ResourcePatternResolver
Resource[] resources = context.getResources("classpath*:com/example/**/mapper/*.xml");
// 支援 Ant 模式:classpath*:、file:、http:、jar: 等
// BeanFactory 僅支援單一 Resource
Resource resource = factory.getResource("classpath:config.xml"); // 無通配符支援
4. 環境抽象與 Profile
// ApplicationContext 整合 Environment
Environment env = context.getEnvironment();
String activeProfile = env.getActiveProfiles()[0]; // 獲取激活 profile
String dbUrl = env.getProperty("jdbc.url"); // 統一屬性訪問
// BeanFactory:無 EnvironmentCapable,需自行管理 Properties
5. 生命週期管理 (Lifecycle)
// ApplicationContext 實現 Lifecycle
context.start(); // 調用所有實現 Lifecycle 的 Bean 的 start()
context.stop(); // 調用 stop()
// 典型應用:定時任務啟動/停止、消息監聽器啟動/停止、連接池預熱
@Component
public class ScheduledTaskManager implements Lifecycle, SmartLifecycle {
@Override public void start() { scheduler.start(); }
@Override public void stop() { scheduler.shutdown(); }
@Override public int getPhase() { return Integer.MAX_VALUE; } // 最後啟動,最先停止
}
五、選型決策指南
1. 必須使用 ApplicationContext 的場景
- ✅ Spring MVC / Spring Boot Web 應用
- ✅ 需要聲明式事務 (@Transactional)
- ✅ 需要 AOP 切面編程
- ✅ 國際化、事件驅動、定時任務
- ✅ 整合第三方框架 (MyBatis, Redis, RabbitMQ, Kafka)
- ✅ 生產環境部署(需要啟動時檢測配置錯誤)
2. 可考慮 BeanFactory 的場景
- ⚡ 單元測試:只需驗證特定 Bean 邏輯,不需完整容器
- ⚡ 輕量級獨立應用:命令行工具、批處理腳本、內存極度受限設備
- ⚡ 動態 Bean 註冊:框架開發、插件系統、運行時根據條件註冊 Bean
- ⚡ 性能極度敏感啟動:毫秒級啟動要求的 Serverless 函數
3. 現代最佳實踐:Spring Boot 自動配置
@SpringBootApplication // 組合:@Configuration + @EnableAutoConfiguration + @ComponentScan
public class Application {
public static void main(String[] args) {
// 內部創建 AnnotationConfigApplicationContext 或 AnnotationConfigWebApplicationContext
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
// 仍可獲取底層 BeanFactory 進行高級操作
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
}
}
六、源碼級核心差異總結表
| 核心方法/特性 | BeanFactory | ApplicationContext | 關鍵實現類 |
| getBean() | 基礎查找 | 繼承 + 事件發布 + 環境解析 | AbstractBeanFactory / AbstractApplicationContext |
| 預實例化 | 無 | refresh() → finishBeanFactoryInitialization() | DefaultListableBeanFactory.preInstantiateSingletons() |
| 國際化 | 無 | MessageSource 整合 | AbstractApplicationContext.initMessageSource() |
| 事件發布 | 無 | ApplicationEventPublisher | AbstractApplicationContext.publishEvent() |
| 資源模式解析 | 單一 Resource | ResourcePatternResolver (Ant) | PathMatchingResourcePatternResolver |
| 環境抽象 | 無 | Environment + PropertySource | AbstractApplicationContext.initPropertySources() |
| 生命週期 | 無 | Lifecycle + SmartLifecycle | AbstractApplicationContext.start()/stop() |
| Web 感知 | 無 | ServletContextAware + Web 環境作用域 | XmlWebApplicationContext / AnnotationConfigWebApplicationContext |
總結
BeanFactory 是 Spring 的「心臟」,提供最核心的 IoC 能力;ApplicationContext 是「大腦」,整合了企業級開發所需的全部周邊能力。
實際開發中 99% 場景直接使用 ApplicationContext(或 Spring Boot 自動配置)。只有在編寫框架代碼、極度精簡測試、Serverless 等特殊場景才需直接操作 BeanFactory。理解兩者差異,本質是理解 Spring 容器從「輕量級 IoC」演進為「企業級應用平台」的架構演進史。