要理解 BeanFactory
和 ApplicationContext
的区别,首先需要了解它们都是 Spring 框架中用于管理 Bean 生命周期和依赖注入的核心接口。但它们在功能、特性和使用场景上有一些关键的不同。
BeanFactory
BeanFactory 是 Spring IoC 容器的基础接口,它提供了配置框架和基础功能来管理任何类型的对象。它是 Spring 中最简单的容器,负责实例化、配置和管理 Bean。但是,它的功能相对有限,主要提供核心的依赖注入功能。
- 懒加载(Lazy Loading):默认情况下,BeanFactory 只有在实际请求某个 Bean 时才会初始化该 Bean。这种方式可以节省资源,特别是在应用程序启动时间较长或不需要立即使用某些 Bean 的情况下。
- 基础功能:只实现了最基本的 IoC 功能,比如通过名称或类型检索 Bean、注册 Bean 等。
- 适合场景:对于那些对内存使用非常敏感或者只需要最基本 IoC 功能的应用来说,
BeanFactory
就足够了。
ApplicationContext
ApplicationContext 扩展了 BeanFactory
接口,添加了许多企业级功能,使其成为更强大、更全面的容器。除了包含 BeanFactory
的所有功能之外,它还增加了以下特性:
- 主动加载(Eager Loading):与
BeanFactory
不同,ApplicationContext
在初始化时就会创建并配置所有的单例 Bean。这确保了当你的应用准备好接收请求时,所有必要的组件都已经准备好了。 - 国际化支持:
ApplicationContext
提供了方便的方法来解析消息,支持国际化(i18n),使得构建多语言应用变得更加容易。 - 事件发布:支持发布事件到监听器,允许实现复杂的交互模式。
- 资源访问:简化了文件资源的访问方式,如读取配置文件等。
- AOP 集成:更容易地将 AOP 功能集成进应用中,无需手动配置代理。
这样来看有点干燥无味,下面还是来看代码的生动形象一点
1.使用 BeanFactory
步骤:
(1) 配置文件 (beans.xml)
首先,我们定义一个简单的 Spring 配置文件 beans.xml
,描述我们的 Bean。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 定义一个简单的 Bean -->
<bean id="myService" class="com.example.MyService">
<property name="message" value="Hello from BeanFactory!" />
</bean>
</beans>
(2) 创建 Bean 类
创建一个简单的 Java 类 MyService
,它会被 Spring 管理。
package com.example;
public class MyService {
private String message;
public void setMessage(String message) {
this.message = message;
}
public void showMessage() {
System.out.println(message);
}
}
(3) 使用 BeanFactory 加载 Bean
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class MainApp {
public static void main(String[] args) {
// 初始化 BeanFactory
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
// 获取 Bean 实例
MyService myService = (MyService) factory.getBean("myService");
// 调用方法
myService.showMessage();
}
}
输出结果:
Hello from BeanFactory!
2.使用 ApplicationContext
步骤:
(1) 配置文件 (beans.xml)
与前面的 beans.xml
文件相同,你可以复用它。
(2) 创建 Bean 类
同样复用前面的 MyService
类。
(3) 使用 ApplicationContext 加载 Bean
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
// 初始化 ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 获取 Bean 实例
MyService myService = context.getBean("myService", MyService.class);
// 调用方法
myService.showMessage();
}
}
输出结果:
Hello from BeanFactory!
两者的区别体现在哪里?
为了更好地理解两者的区别,我们可以通过以下几点对比:
1. Bean 的加载时机
- BeanFactory:懒加载(Lazy Loading)。只有当你调用
getBean()
方法时,Bean 才会被初始化。 - ApplicationContext:主动加载(Eager Loading)。在容器启动时,所有的单例 Bean 都会被提前初始化。
测试懒加载 vs 主动加载
在 MyService
类中添加一个构造函数:
public MyService() {
System.out.println("MyService Bean is created!");
}
运行上面的两个例子,发现:
- 使用
BeanFactory
时,只有调用getBean()
时才会打印 “MyService Bean is created!”。 - 使用
ApplicationContext
时,在容器启动时就会打印 “MyService Bean is created!”。
2. 功能差异
特性 | BeanFactory | ApplicationContext |
---|---|---|
基础 IoC 功能 | ✅ | ✅ |
懒加载 | ✅ | ❌ |
国际化支持 | ❌ | ✅ |
事件传播 | ❌ | ✅ |
AOP 集成 | ❌ | ✅ |
资源访问(文件等) | ❌ | ✅ |
实际项目中的选择
什么时候用 BeanFactory?
- 如果你的项目对内存和性能要求非常高,且只需要最基础的依赖注入功能。
- 例如:嵌入式系统或资源受限的环境。
什么时候用 ApplicationContext?
- 绝大多数情况下,推荐使用
ApplicationContext
。 - 如果你需要国际化、事件发布、AOP 等功能,或者希望所有单例 Bean 在应用启动时就准备好。
- 例如:Web 应用、微服务架构、Spring Boot 项目等。
虽然在使用框架的时候,基本不用再编写这样的程序,但是需要涉及到自主编辑框架的时候,或者需要进行高度的客制化的需求时,或多或少会在涉及相关源码的部分,还是需要去学习一番,可以不用,但不能不会。