The BeanFactory API

BeanFactory API 为 Spring 的 IoC 功能提供了基础。它的特定协定主要用于与 Spring 的其他部分和相关的第三方框架集成,而它的 DefaultListableBeanFactory 实现是高级别 GenericApplicationContext 容器中的关键委托。 BeanFactory 和相关接口(如 BeanFactoryAwareInitializingBeanDisposableBean)是其他框架组件的重要集成点。通过不需要任何注解甚至反射,它们允许容器及其组件之间进行非常有效的交互。应用程序级 Bean 可以使用相同的回调接口,但通常首选声明式依赖注入,通过注解或通过程序化配置实现。 请注意,核心 BeanFactory API 级别及其 DefaultListableBeanFactory 实现不会对配置格式或要使用的任何组件注解做出假设。所有这些特性都通过扩展(如 XmlBeanDefinitionReaderAutowiredAnnotationBeanPostProcessor)进入,并在共享的 BeanDefinition 对象上作为核心元数据表示进行操作。这就是 Spring 的容器如此灵活且可扩展的原因。

BeanFactory or ApplicationContext?

本部分介绍 BeanFactoryApplicationContext 容器级别之间的差异,以及对引导的影响。

除非有充分的理由不这样做,否则应使用 ApplicationContext,使用 GenericApplicationContext 及其子类 AnnotationConfigApplicationContext 作为自定义引导的常见实现。这些是 Spring 的核心容器的通用实现,适用于所有常见目的:加载配置文件、触发类路径扫描、以编程方式注册 Bean 定义和带注解的类,以及(从 5.0 版开始)注册功能性 Bean 定义。

由于 ApplicationContext 包含 BeanFactory 的所有功能,所以通常建议使用 ApplicationContext 而非普通的 BeanFactory,除非需要对 Bean 处理进行完全控制。在 ApplicationContext(如 GenericApplicationContext 实现)内部,根据惯例(即按 Bean 名称或按 Bean 类型 - 特别是后置处理器)检测到几种 Bean,而普通的 DefaultListableBeanFactory 不识别任何特殊 Bean。

对于许多扩展的容器功能,例如注解处理和 AOP 代理,xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp[BeanPostProcessor`扩展点至关重要。如果您只使用纯`DefaultListableBeanFactory,则默认情况下无法检测并激活此类后置处理器。这种情况可能会令人困惑,因为您的 Bean 配置实际上并没有什么问题。相反,在这种情况下,需要通过附加设置完全引导容器。

下表列出了 BeanFactoryApplicationContext 接口和实现提供的功能。

Table 1. Feature Matrix
Feature BeanFactory ApplicationContext

Bean instantiation/wiring

Yes

Yes

Integrated lifecycle management

No

Yes

Automatic BeanPostProcessor registration

No

Yes

Automatic BeanFactoryPostProcessor registration

No

Yes

方便的 MessageSource 访问(用于国际化)

No

Yes

Built-in ApplicationEvent publication mechanism

No

Yes

要使用 DefaultListableBeanFactory 明确注册 bean 后处理器,需要以编程方式调用 addBeanPostProcessor,如下例所示:

  • Java

  • Kotlin

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
val factory = DefaultListableBeanFactory()
// populate the factory with bean definitions

// now register any needed BeanPostProcessor instances
factory.addBeanPostProcessor(AutowiredAnnotationBeanPostProcessor())
factory.addBeanPostProcessor(MyBeanPostProcessor())

// now start using the factory

要将 BeanFactoryPostProcessor 应用于普通的 DefaultListableBeanFactory,需要调用其 postProcessBeanFactory 方法,如下例所示:

  • Java

  • Kotlin

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);
val factory = DefaultListableBeanFactory()
val reader = XmlBeanDefinitionReader(factory)
reader.loadBeanDefinitions(FileSystemResource("beans.xml"))

// bring in some property values from a Properties file
val cfg = PropertySourcesPlaceholderConfigurer()
cfg.setLocation(FileSystemResource("jdbc.properties"))

// now actually do the replacement
cfg.postProcessBeanFactory(factory)

在这两种情况下,明确的注册步骤都是非常不便的,这也是在基于 Spring 的应用程序中更喜欢各种 ApplicationContext 变体而不是普通的 DefaultListableBeanFactory 的原因,尤其是在在典型的企业设置中依赖 BeanFactoryPostProcessorBeanPostProcessor 实例以扩展容器功能的情况下。

AnnotationConfigApplicationContext 注册了所有常见的注释后处理器,并可能通过配置注释(例如 @EnableTransactionManagement)引入其他处理器。在 Spring 基于注释的配置模型的抽象层级中,bean 后处理器的概念变成了纯粹的内部容器细节。