https://docs.spring.io/spring-framework/reference/core/beans/beanfactory.html
BeanFactory
API 提供了 Spring 控制反转(IoC)功能的基础,其特定接口主要与其它Spring 组件以及相关的第三方框架集成使用,而它的 DefaultListableBeanFactory
实现是高级 GenericApplicationContext
容器中的一个关键代理。
BeanFactory
及相关接口(如 BeanFactoryAware
、InitializingBean
、DisposableBean
)是其它框架组件的重要集成点。它们不要求任何注解或甚至反射,允许容器与其组件之间非常高效的交互。应用级别的 bean 可能会使用相同的回调接口,但通常更倾向于通过注解或编程配置来声明式地注入依赖。
核心的 BeanFactory
API 层面及其 DefaultListableBeanFactory
实现并不对配置格式或任何组件注解做出假设。所有这些变体都是通过扩展(如 XmlBeanDefinitionReader
和 AutowiredAnnotationBeanPostProcessor
)引入的,并且操作共享的 BeanDefinition
对象作为核心元数据表示。这是使得 Spring 容器如此灵活和可扩展的本质所在。
BeanFactory 还是 ApplicationContext?
本节解释了 BeanFactory
和 ApplicationContext
容器级别之间的差异,以及它们对引导过程的影响。
除非你有充分的理由不这么做,否则应该使用 ApplicationContext
,其中 GenericApplicationContext
及其子类 AnnotationConfigApplicationContext
是自定义引导常见的实现。这些是进入 Spring 核心容器的主要入口,适用于所有常见用途:加载配置文件、触发类路径扫描、以编程方式注册 bean 定义和注解类,以及(自 5.0 版本起)注册函数式 bean 定义。
因为 ApplicationContext
包含了 BeanFactory
的所有功能,所以通常推荐使用它而不是普通的 BeanFactory
,除非在需要完全控制 bean 处理的场景中。在 ApplicationContext
内部(例如 GenericApplicationContext
实现),多种类型的 beans 可以通过约定检测到(即通过 bean 名称或 bean 类型——特别是后处理器),而一个普通的 DefaultListableBeanFactory
对任何特殊的 beans 都是不可知的。
对于许多扩展的容器特性,如注解处理和 AOP 代理,BeanPostProcessor
扩展点是必不可少的。如果仅使用普通的 DefaultListableBeanFactory
,这样的后处理器默认不会被检测和激活。这种情况可能会令人困惑,因为你的 bean 配置实际上没有任何问题。相反,在这种情况下,需要通过额外的设置来完全引导容器。
下表列出了 BeanFactory
和 ApplicationContext
接口及其实现提供的特性。
要显式地向 DefaultListableBeanFactory
注册一个 bean 后处理器,你需要像下面的例子那样以编程方式调用 addBeanPostProcessor
:
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// populate the factory with bean definitions
// now register any needed BeanPostProcessor instances
factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
factory.addBeanPostProcessor(new MyBeanPostProcessor());
// now start using the factory
要将 BeanFactoryPostProcessor
应用于普通的 DefaultListableBeanFactory
,需要调用其 postProcessBeanFactory
方法,如下例所示:
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));
// bring in some property values from a Properties file
PropertySourcesPlaceholderConfigurer cfg = new PropertySourcesPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));
// now actually do the replacement
cfg.postProcessBeanFactory(factory);
在这两种情况下,显式注册步骤都不方便,这就是为什么在 Spring 支持的应用程序中,尤其是在典型的企业环境中依赖 BeanFactoryPostProcessor
和 BeanPostProcessor
实例来扩展容器功能时,更倾向于使用各种 ApplicationContext
变体而不是普通的 DefaultListableBeanFactory
。
AnnotationConfigApplicationContext
注册了所有常见的注解后处理器,并且可能通过配置注解(如 @EnableTransactionManagement
)在底层引入额外的处理器。在 Spring 基于注解的配置模型的抽象层面上,bean 后处理器的概念变成了容器内部的一个细节。