📚深入浅出:BeanFactory与ApplicationContext背后的故事,带你领略Spring IoC容器的双重魅力及其关键差异!

关注微信公众号 "程序员小胖" 每日技术干货,第一时间送达!

引言

在Java开发领域,Spring框架无疑是众多开发者手中的利器,其核心在于两大IoC容器------BeanFactory与ApplicationContext。这两者如同双引擎,驱动着应用程序的构造与运行,却又各有千秋。

然而,要想真正发挥Spring框架的优势,必须深刻理解这两个容器的本质与区别。本文将聚焦BeanFactory与ApplicationContext的实现原理,详解它们在Bean管理、依赖注入等方面的异同,结合实用案例剖析应用场景,以便您在实践中,既能洞察底层逻辑,又能游刃有余地驾驭不同情境下的容器功能。

BeanFactory

实现原理

BeanFactory是Spring框架IoC(Inversion of Control,控制反转)容器的核心接口,它负责管理和创建应用程序中的Bean(即Java对象)。BeanFactory提供了诸如Bean的定义、实例化、配置以及依赖注入等功能。基本实现流程如下:

  1. 读取配置: BeanFactory 是 Spring 框架中用来读取配置并管理 Bean 的基本容器接口。要使用 BeanFactory 读取配置。读取配置有几种方式你知道吗?评论区交流下。

通过 Java 配置类读取配置代码示例:

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

  @Bean
  public UserService userService() {
      return new UserServiceImpl();
  }

  @Bean
  public OrderService orderService() {
      return new OrderServiceImpl(userService()); // 引用外部 Bean
  }
}
java 复制代码
// 使用 AnnotationConfigApplicationContext 并传入 Java 配置类
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  1. Bean定义:在配置文件中,每个Bean都有相应的定义,包括其类型、构造函数参数、属性值、依赖关系等等。Bean定义有几种实现方式你知道吗?评论区交流下。

Spring的注解来定义和配置Bean

java 复制代码
@Component
public class ExampleBean {
private String propertyName;

@Autowired
private AnotherBean anotherBean;

@Value("${config.value}")
private String configValue;

public void initialize() {...} // 初始化方法
public void cleanup() {...} // 销毁方法
}
  1. Bean实例化与依赖注入:当调用BeanFactory的getBean(String beanName)方法时,如果Bean尚未被实例化,容器会根据定义信息通过反射创建实例,并处理依赖关系,将其他Bean注入到所需Bean中。Bean实例化有几种实现方式你知道吗?评论区交流下。

  2. 延迟初始化:BeanFactory支持懒加载或延迟初始化,即只有在请求某个Bean时才会实例化它。延迟初始化有几种实现方式你知道吗?评论区交流下。 自Spring 4.0开始,可以使用@Lazy注解来实现Bean的延迟初始化

java 复制代码
@Component
@Lazy
public class ExampleBean {
  // ...
}

@Configuration
public class AppConfig {
  @Lazy
  @Bean
  public ExampleBean exampleBean() {
      return new ExampleBean();
  }
}

应用场景

  • 服务定位与依赖解决:在大型项目中,各个组件可以通过BeanFactory获取所需的协作对象,无需自行创建和维护这些对象的生命周期。
  • 配置集中管理:所有Bean的配置都集中在配置文件中,便于统一管理和维护。
  • AOP支持:通过集成AspectJ等技术,BeanFactory可以自动处理切面逻辑,实现面向切面编程。
  • 资源管理:除了管理Bean之外,BeanFactory还能够管理各种资源,例如数据库连接、线程池等。

BeanFactory作为IoC容器的基本接口,专注于Bean的生命周期管理、依赖注入等基础功能,采取懒加载策略,仅在首次请求时实例化Bean。它的简洁设计使其轻量高效,适用于对启动速度和资源消耗敏感的应用场景。

ApplicationContext

实现原理

ApplicationContext是Spring IoC容器的高级版本,它继承自BeanFactory接口并提供了更多的企业级服务。换句话说就是ApplicationContext具备BeanFactory的所有功能并在此基础上做了增强,包含但不限于以下几点:

  1. 消息源(MessageSource):用于实现国际化和消息查找。
  2. 资源加载(ResourceLoader):可以从多种资源位置如文件系统、类路径加载资源。
  3. 事件传播(ApplicationEventPublisher):支持发布和监听应用事件。
  4. 自动装配(AutowiredAnnotationBeanPostProcessor):支持基于注解的自动装配。

区别:

  1. 初始化时机:BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法 才会抛出异常。
  2. 加载方式:ApplicationContext,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。ApplicationContext启动后预载入所有的单实例Bean,通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。
  3. 内存占用问题:相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。
  4. 创建方式:BeanFactory通常以编程的方式被创建,ApplicationContext还能以声明的方式创建,如使用ContextLoader。
  5. 注册方式:BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册

总结

在深入探索Spring框架的核心容器------BeanFactory与ApplicationContext的过程中,我们了解到两者均扮演着IoC(控制反转)容器的角色,但各自有着不同的设计目标与适用场景。

BeanFactory作为IoC容器的基本接口,专注于Bean的生命周期管理、依赖注入等基础功能,采取懒加载策略,仅在首次请求时实例化Bean。它的简洁设计使其轻量高效,适用于对启动速度和资源消耗敏感的应用场景。

相比之下,ApplicationContext继承并扩展了BeanFactory的功能,提供了更为丰富的企业级服务。它在启动时预先加载所有单例Bean,增强了诸如国际化支持(MessageSource)、事件传播(ApplicationEventPublisher)、自动装配(通过注解驱动)等功能。此外,ApplicationContext还完善了Bean的生命周期管理机制,允许开发者利用特定的回调接口更好地控制Bean的初始化与销毁过程。

简而言之,BeanFactory适合对容器功能需求较为简单的环境,而ApplicationContext则是在保持IoC容器功能的基础上,进一步满足了复杂应用架构下的各类增值服务需求。在实际开发中,大部分情况下我们会选择使用ApplicationContext以充分利用其诸多优势,从而构建更为健壮和灵活的应用程序。

相关推荐
xlsw_2 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹3 小时前
基于java的改良版超级玛丽小游戏
java
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭4 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫4 小时前
泛型(2)
java
超爱吃士力架4 小时前
邀请逻辑
java·linux·后端
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石4 小时前
12/21java基础
java
李小白664 小时前
Spring MVC(上)
java·spring·mvc
GoodStudyAndDayDayUp5 小时前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶5 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb