BeanFactory API

BeanFactory API 提供了 Infra IoC 功能的基础。它的具体契约大多用于与 Infra 的其他部分以及相关的第三方框架集成,其 StandardBeanFactory 实现是高级 GenericApplicationContext 容器内的一个关键委托。

BeanFactory 及其相关接口(如 BeanFactoryAwareInitializingBeanDisposableBean) 是其他框架组件的重要集成点。通过不需要任何注解甚至反射,它们允许容器与其组件之间进行非常高效的交互。 应用级别的 Bean 可以使用相同的回调接口,但通常更喜欢声明式依赖注入,可以通过注解或编程配置来实现。

请注意,核心 BeanFactory API 层及其 StandardBeanFactory 实现不对要使用的配置格式或任何组件注解做出假设。所有这些变体都通过扩展(如 XmlBeanDefinitionReaderAutowiredAnnotationBeanPostProcessor)进入,并在共享的 BeanDefinition 对象上操作作为核心元数据表示。 这就是使 Infra 容器如此灵活和可扩展的本质。

BeanFactory vs ApplicationContext?

这一部分解释了 BeanFactoryApplicationContext 容器级别之间的区别,以及对引导的影响。

除非有充分理由不这样做,否则应该使用 ApplicationContext,其常见的自定义引导实现为 GenericApplicationContext 及其子类 AnnotationConfigApplicationContext。 这些是 Infra 核心容器的主要入口点,用于所有通用目的:加载配置文件,触发类路径扫描, 以编程方式注册 bean 定义和注解类,以及注册功能 bean 定义。

因为 ApplicationContext 包含了 BeanFactory 的所有功能,所以通常建议使用 ApplicationContext 而不是普通的 BeanFactory,除非需要对 bean 处理具有完全控制权。在 ApplicationContext 内(例如 GenericApplicationContext 实现),按照约定检测到几种类型的 bean(即,按照 bean 名称或 bean 类型 — 特别是后处理器) ,而普通的 StandardBeanFactory 对于任何特殊的 bean 都是不可知的。

对于许多扩展容器功能,例如注解处理和 AOP 代理,BeanPostProcessor 扩展点 是必不可少的。如果仅使用普通的 StandardBeanFactory,这样的后处理器将不会被默认检测和激活。 这种情况可能会令人困惑,因为您的 bean 配置实际上并没有问题。相反,在这种情况下,需要通过额外的设置完全引导容器。

以下表格列出了 BeanFactoryApplicationContext 接口及其实现提供的功能。

Table 1. Feature 对比
特性 BeanFactory ApplicationContext

Bean 实例化/装配

Yes

Yes

集成的生命周期管理

No

Yes

BeanPostProcessor 自动注册

No

Yes

BeanFactoryPostProcessor 自动注册

No

Yes

好用的 MessageSource 访问(用于国际化)

No

Yes

内置的 ApplicationEvent 发布机制

No

Yes

要将一个Bean后处理器明确注册到`StandardBeanFactory`,你需要以编程方式调用`addBeanPostProcessor`,就像以下示例所示:

StandardBeanFactory factory = new StandardBeanFactory();
// 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`应用于普通的`StandardBeanFactory`,你需要调用其`postProcessBeanFactory`方法,就像以下示例所示:

StandardBeanFactory factory = new StandardBeanFactory();
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);

在这两种情况下,明确注册步骤都不太方便,这就是为什么在 Infra 支持的应用程序中,各种 ApplicationContext 变体优先于普通的 StandardBeanFactory ,特别是在典型企业设置中依赖于 BeanFactoryPostProcessorBeanPostProcessor 实例以扩展容器功能时。

AnnotationConfigApplicationContext 已经注册了所有常见的注解后处理器, 并且可能通过配置注解(例如 @EnableTransactionManagement )在底层引入额外的处理器。 在基于注解的配置模型的抽象级别上,Bean后处理器的概念仅仅是容器的内部细节。