0%

What is the real Spring IoC container

note:本文基于 spring-framework 5.2.2.RELEASE

What is the real Spring IoC container? BeanFactory or ApplicationContext?

官网描述

Spring 官网 beans-introduction 描述中可以得到以下信息:

  • 源码工程中的 org.springframework.beansorg.springframework.context 包是 Spring Framework 的 IoC container 基础
  • BeanFactory 接口提供了一种高级配置机制能够管理任何类型的对象
  • ApplicationContextBeanFactory 的一个子类,它增加了以下功能:
    • 更容易和 Spring AOP 集成
    • 消息资源处理(用于国际化)
    • 事件发布
    • 应用层面特定上下文,例如用于 web 应用的 WebApplicationContext
  • 简而言之,BeanFactory 提供了配置框架和基础的功能,而 ApplicationContext 增加了更多企业级特性的功能。ApplicationContextBeanFactory 的一个完整超集

BeanFactory or ApplicationContext?

BeanFactoryApplicationContext 应该如何选择?

Spring 官网 BeanFactory or ApplicationContext 中也做了详细的描述。重点是这两句:

You should use an ApplicationContext unless you have a good reason for not doing so
(你应该使用 ApplicationContext,除非你有很好的理由不使用它)
Because an ApplicationContext includes all the functionality of a BeanFactory, it is generally recommended over a plain BeanFactory
(因为 ApplicationContext 包含了 BeanFactory 的所有功能,通常建议使用)

还附了一张关于 Feature Matrix(功能矩阵) 的表来描述 BeanFactoryApplicationContext 接口和实现所提供的功能:

特性 BeanFactory ApplicationContext
Bean 实例化/加工(wiring) Yes Yes
集成生命周期管理 No Yes
自动注册 BeanPostProcessor No Yes
自动注册 BeanFactoryPostProcessor No Yes
方便 MessageSource 访问(用于国际化) No Yes
内置 ApplicationEvent 发布机制 No Yes

可以看出,官方更推荐使用 ApplicationContext,但这并不代表 BeanFactory 就没有使用场景,只是场景真的比较有限,具体可参考官方文档描述。

实现原理

ApplicationContext Java Diagrams

ApplicationContext diagrams

从图中可以可以反映出:ApplicationContext 自身就是一个 BeanFactory 并且它还拥有其他功能。

那么,ApplicationContextBeanFactory 的一个完整超集这是如何实现的呢?

ApplicationContext internal BeanFactory

ApplicationContext 源码中,getAutowireCapableBeanFactory() 方法注释中有个重要的字眼:internal BeanFactory

这个字眼是否意味着,虽然 ApplicationContext 是一个 BeanFactory,但是其内部还有一个 BeanFactory?如果真是这样,是否多此一举呢?

顺着该方法注释提示去 @see ConfigurableApplicationContext#getBeanFactory() 源码,发现该方法注释第一句就解答了疑问:

Return the internal bean factory of this application context. Can be used to access specific functionality of the underlying factory.
(返回此应用程序上下文的内部 bean factory。可用于访问基础 factory 的特定功能)

How to set internal BeanFactory

这里就有一个新问题,这个 internal BeanFactory 是如何设置进去的?

按常理来讲,既然有 getBeanFactory() 方法,那应该也有一个 setBeanFactory() 方法用来把 beanFactory set 进去,但是很遗憾,源码中并没有 setBeanFactory() 方法。

继续查看 getBeanFactory() 的实现,发现有两个类实现了该方法:AbstractRefreshableApplicationContextGenericApplicationContext

继续看这两个类的源码会发现,这两个类里都有一个非常重要的内部属性:DefaultListableBeanFactory beanFactory,而 getBeanFactory() 方法返回的 internal BeanFactory 正是这个 beanFactory!

这种方式有点像代理,通过组合的方式把 BeanFactory 的实现 DefaultListableBeanFactory 组合进来,并不是完全去抽象或继承该类。

题外:其实这两个类都很重要,Spring 中”著名”的两个类都继承自它们:

  • ClassPathXmlApplicationContext extends … extends AbstractRefreshableApplicationContext
  • AnnotationConfigApplicationContext extends GenericApplicationContext

应用 internal BeanFactory

可以看下 Spring 里 AbstractApplicationContext 里的各个 getBean() 方法的实现,都是先调用 getBeanFactory() 再调用 getBean():

1
2
3
4
5
@Override
public Object getBean(String name) throws BeansException {
assertBeanFactoryActive();
return getBeanFactory().getBean(name);
}

可以看出,ApplicationContext 其实并不具备依赖查找的能力,都是委托给自己的 internal beanFactory 来实现。

同时也反映了,BeanFactory 其实是最底层的 IoC 容器,ApplicationContext 是在 BeanFactory 的基础上增加了一些特性。

Summary

综上,可以说,BeanFactory 含有的能力 ApplicationContext 都有,并且 ApplicationContext 提供了更多的特性。

再看官网这句话,就豁然开朗了: BeanFactory 提供了配置框架和基础的功能,而 ApplicationContext 增加了更多企业级特性的功能。ApplicationContextBeanFactory 的一个完整超集。


欢迎关注我的其它发布渠道