前言
在Spring框架中有两个重要的容器:BeanFactory 和 ApplicationContext。两者在Spring应用程序中扮演着关键的角色,但它们之间存在一些区别。因此要想真正发挥Spring框架的优势,需要深刻理解这两个容器的本质与区别。
BeanFactory
在Spring框架中,BeanFactory 是Spring IOC容器的实现的一个核心接口。
BeanFactory 负责创建和管理Bean、依赖注入、延迟初始化等功能。
org.springframework.beans.factory.BeanFactory
/**
* The root interface for accessing a Spring bean container.(用于访问 Spring bean 容器的根接口。)
* ...
*/
public interface BeanFactory {
...
}
在BeanFactory接口的注释中也可以看到BeanFactory是用于访问 Spring bean 容器的根接口。
ApplicationContext
ApplicationContext是BeanFactory的子接口,在Spring默认使用ApplicationContext。
ApplicationContext提供了更多的企业级功能和更好的开发体验。如:
支持更多的配置方式,如基于注解的配置、Java配置类,支持自动装配等。
org.springframework.context.ApplicationContext
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
...
}
两者的区别
- 初始化时机:
- BeanFactory 采用懒加载策略,只有在第一次请求时才会创建Bean实例。这种方式在内存使用上比较高效,特别是当应用中有大量的Bean时。
- ApplicationContext 默认采用立即初始化策略,会在应用启动时立即创建所有的单例Bean。也可以使用@Lazy注解来实现Bean的延迟初始化。这种方式虽然在启动时可能会消耗更多的资源和时间,但在运行时可以更快地响应请求,因为所需的 Bean 已经提前创建好了。
- 例如,在一个 Web 应用的启动阶段,ApplicationContext会把所有配置为单例的服务层和数据访问层的 Bean 都创建好,当用户请求到达时,可以直接使用这些 Bean 进行业务处理,减少了等待 Bean 创建的时间。
- 在Spring框架中,默认情况下使用的是ApplicationContext
- 自动装配:
- ApplicationContext 支持自动装配,可以自动检测并注入依赖。
- BeanFactory 不支持自动装配,需要显式地配置依赖关系。
- 额外的功能:
- ApplicationContext 提供了更多企业级功能,如国际化、事件传播、资源访问等。
- ApplicationContext 支持更多的配置方式,如基于注解的配置、Java配置类等。
- 使用场景
- BeanFactory:适用于资源受限的环境或者对内存占用比较敏感的场景,以及简单的应用程序,这些场景下可能不需要ApplicationContext提供的丰富功能。例如,在一个简单的工具类库中,只需要创建和管理少量的 Bean,并且对性能和资源占用有严格要求,使用BeanFactory就足够了。
- ApplicationContext:更适合于企业级的复杂应用,特别是 Web 应用或大型的独立应用。例如,在一个大型的电子商务 Web 应用中,需要处理用户的多种语言请求、发布和监听业务事件(如订单创建事件、库存更新事件等),并且需要加载各种配置文件和资源,这时ApplicationContext是更好的选择。
两者的联系
-
继承关系:ApplicationContext 继承自 BeanFactory,因此 ApplicationContext 包含了 BeanFactory 的所有功能。所以,在
ApplicationContext中可以使用BeanFactory提供的方法来获取和管理 Bean。
例如,可以通过applicationContext.getBeanFactory()方法获取底层的BeanFactory实例,然后使用BeanFactory的方法来操作 Bean。 -
目的相同:两者都是用来管理Spring容器中的bean,包括bean的创建、配置、销毁等生命周期管理。
-
依赖注入:两者都支持依赖注入,但 ApplicationContext 提供了更丰富的自动注入功能。
为什么在Spring框架中,默认情况下使用的是ApplicationContext?
在启动spring时,因为默认使用ApplicationContext,所以会实例化所有的单例bean,但是这样有两个问题:
- 因为要实例化所有的单例bean,所以启动时间会变长。
- 会导致浪费内存。
所以为什么要使用ApplicationContext而不使用BeanFactory呢?
BeanFactory采用延迟加载(懒加载)的方式,在获取 Bean 时才会创建 Bean 实例。这种方式在内存使用上比较高效,特别是当应用中有大量的 Bean,但在实际运行过程中只有部分 Bean 会被使用时。但是这样也会出现问题:
- 因为BeanFactory采用懒加载的方式,所以在第一次请求时需要等待创建Bean实例,增加了响应时间。
- 因为采用懒加载的方式,所以不能像ApplicationContext一样,在启动项目时提前将问题暴露出来。只有在运行时才会报错,会让问题难以排查
- 虽然BeanFactory在一开始会节省内存,但是当项目运行久了仍然会创建Bean实例占用内存。如果内存不足,使用ApplicationContext一开始加载所有的bean会直接报错。而使用懒加载只会让问题延后了,问题并没有得到解决。
因此在项目运行流畅、提前暴露问题、内存等考虑下,选择ApplicationContext是明智之举。