【Spring源码三千问】ApplicationContext 与 BeanFactory 的作用是什么?它们有什么区别?

前言

我们在讲 Spring 容器器,通常指的是 Spring IoC 容器。
跟 Spring IoC 容器相关的类、接口有 BeanFactory、DefaultListableBeanFactory、ApplicationContext 等。
这些类、接口的作用是什么?有什么区别?

下面我们就来研究一下!

版本约定

Spring 5.3.9 (通过 SpringBoot 2.5.3 间接引入的依赖)

正文

BeanFactory 的整体类图如下:

BeanFactory.png

阅读源码注释可以知道,BeanFactory 是用户访问 Spring bean 容器的根接口。
DefaultListableBeanFactory 是 BeanFactory 的默认实现类。
DefaultListableBeanFactory 是一个成熟的 bean 工厂,它实现了 BeanDefinitionRegistrySingletonBeanRegistry,说明它具有注册 BeanDefinition 的能力,同时还具有注册 bean 的能力。

BeanFactory

BeanFactory 是访问 Spring bean 容器的根接口,是 bean 的中心注册表(注册中心)。
通常,BeanFactory 会加载存储在配置源(如XML文档)中的 bean definition。

HierarchycalBeanFactory

HierarchycalBeanFactory 是具有层级结构的 BeanFactory,可以获取 parent BeanFactory。
如果在当前 BeanFactory 实例中找不到 bean 的话,它将通过 parent BeanFactory 来寻找 bean。

注意: 如果 BeanFactory 和 parent BeanFactory 中同时定义了一个同名的 bean 的话,那么通过当前 BeanFactory 获取 bean 时,将会以当前 BeanFactory 中的为准。
也就是相当于当前 BeanFactory 实例中的 bean 覆盖了 parent BeanFactory 中同名的 bean。

DefaultListableBeanFactory

DefaultListableBeanFactory 是 BeanFactory 的默认实现类。
它实现了 BeanFactoryBeanDefinitionRegistrySingletonBeanRegistry,是一个功能完善的 BeanFactory,拥有注册 BeanDefinition 和 注册 bean 的能力。

可以发现一个规律:ConfigurableBeanFactory、ConfigurableApplicationContext 等都是配置接口,接口里面会增加一些 getter/setter 方法,来方便的进行属性配置。
所以,Spring 中 ConfigurableXxx 就是一个配置接口。

ApplicationContext

ApplicationContext 是为应用提供配置的核心接口。
ApplicationContext 是 BeanFactory 的子接口,它包含 BeanFactory 的所有功能。
通常建议使用 ApplicationContext,而不是直接使用 BeanFactory。

为什么建议使用 ApplicationContext,而不是直接使用 BeanFactory?
答:因为在使用 BeanFactory 时,注解的处理、AOP代理、BeanPostProcessor 扩展点等容器特性功能是不会自动开启的,需要手动调用方法来实现。
而使用 ApplicationContext 时,这些容器特性会自动开启。
ApplicationContext

BeanFactory-detail.png

可以看到,ApplicationContext 下面有三个子接口: ConfigurableApplicationContext、WebApplicationContext、WebServerApplicationContext
很明显,ConfigurableApplicationContext 是 ApplicationContext 的配置接口;

ApplicationContext vs BeanFactory

BeanFactoryApplicationContext 的对比:
https://docs.spring.io/spring-framework/docs/5.3.9/reference/html/core.html#beans-beanfactory

FeatureBeanFactoryApplicationContext
Bean instantiation/wiringYesYes
Integrated lifecycle managementNoYes
Automatic BeanPostProcessor registrationNoYes
Automatic BeanFactoryPostProcessor registrationNoYes
Convenient MessageSource access (for internalization)NoYes
Built-in ApplicationEvent publication mechanismNoYes

使用 DefaultListableBeanFactory 时,需要调用 addBeanPostProcessor 显式注册 bean post-processor;
要执行 BeanFactoryPostProcessor,需要调用 postProcessBeanFactory() :

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// populate the factory with bean definitions
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
// 加载 BeanDefinition 到 BeanFactory 中        
reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));

// 注册 BeanPostProcessor 到 BeanFactory 中        
factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
factory.addBeanPostProcessor(new MyBeanPostProcessor());

// 添加 Properties 文件中的配置到 BeanFactory 中       
PropertySourcesPlaceholderConfigurer cfg = new PropertySourcesPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));

// now actually do the replacement
// 执行 BeanFactoryPostProcessor        
cfg.postProcessBeanFactory(factory);

小结

BeanFactory、ApplicationContext 都可以称作 Spring IoC 容器。
ApplicationContext 是 BeanFactory 的子接口,功能更加强大,且包含了 BeanFactory 的所有功能。


SpringIoC源码视频讲解:

课程地址
SpringIoC源码解读由浅入深https://edu.51cto.com/sd/68e86

如果本文对你有所帮助,欢迎点赞收藏!

源码测试工程下载:
老王读Spring IoC源码分析&测试代码下载
老王读Spring AOP源码分析&测试代码下载

公众号后台回复:下载IoC 或者 下载AOP 可以免费下载源码测试工程…

阅读更多文章,请关注公众号: 老王学源码
gzh


系列博文:
【老王读Spring IoC-0】Spring IoC 引入
【老王读Spring IoC-1】IoC 之控制反转引入
【老王读Spring IoC-2】IoC 之 BeanDefinition 扫描注册
【老王读Spring IoC-3】Spring bean 的创建过程
【老王读Spring IoC-4】IoC 之依赖注入原理
【老王读Spring IoC-5】Spring IoC 小结——控制反转、依赖注入

相关阅读:
【Spring源码三千问】@Resource 与 @Autowired 的区别
【Spring源码三千问】bean name 的生成规则
【Spring源码三千问】BeanDefinition详细分析
【Spring源码三千问】Spring 是怎样解决循环依赖问题的?
【Spring源码三千问】哪些循环依赖问题Spring解决不了?
【Spring源码三千问】@Lazy为什么可以解决特殊的循环依赖问题?
【Spring源码三千问】BeanDefinition注册、Bean注册、Dependency注册有什么区别?
【Spring源码三千问】Bean的Scope有哪些?scope=request是什么原理?
【Spring源码三千问】为什么要用三级缓存来解决循环依赖问题?二级缓存行不行?一级缓存行不行?

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老王学源码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值