对于最新稳定版本,请使用 Spring Framework 7.0.6spring-doc.cadn.net.cn

BeanFactory API

BeanFactory API 为 Spring 的 IoC 功能提供了底层基础。 其具体的契约主要用于与 Spring 的其他部分以及相关的第三方框架进行集成, 而其 DefaultListableBeanFactory 实现则是高层级 GenericApplicationContext 容器中的一个关键委托组件。spring-doc.cadn.net.cn

BeanFactory 及其相关接口(例如 BeanFactoryAwareInitializingBeanDisposableBean)是其他框架组件的重要集成点。 由于无需任何注解甚至反射,它们能够实现容器与其组件之间非常高效的交互。 应用级别的 Bean 也可以使用相同的回调接口,但通常更倾向于使用声明式的依赖注入方式, 无论是通过注解还是通过编程式配置。spring-doc.cadn.net.cn

请注意,核心的 BeanFactory API 层及其 DefaultListableBeanFactory 实现并不对配置格式或要使用的任何组件注解做出假设。所有这些形式都通过扩展(例如 XmlBeanDefinitionReaderAutowiredAnnotationBeanPostProcessor)引入,并以共享的 BeanDefinition 对象作为核心元数据表示进行操作。 这正是 Spring 容器如此灵活和可扩展的根本所在。spring-doc.cadn.net.cn

BeanFactory or ApplicationContext?

本节解释了 BeanFactoryApplicationContext 容器层级之间的区别,以及它们对启动过程的影响。spring-doc.cadn.net.cn

除非有充分的理由不这样做,否则你应该使用 ApplicationContext,其中 GenericApplicationContext 及其子类 AnnotationConfigApplicationContext 是用于自定义引导的常见实现。这些类是 Spring 核心容器在所有常见用途下的主要入口点:加载配置文件、触发类路径扫描、以编程方式注册 bean 定义和带注解的类,以及(从 5.0 版本起)注册函数式 bean 定义。spring-doc.cadn.net.cn

由于 ApplicationContext 包含了 BeanFactory 的全部功能,因此通常推荐使用 BeanFactory,而非普通的 ApplicationContext,除非在需要完全控制 bean 处理的场景下。在 GenericApplicationContext(例如 DefaultListableBeanFactory 实现)中,会通过约定(即通过 bean 名称或 bean 类型——特别是后处理器)自动检测多种类型的 bean,而普通的 6 则对任何特殊 bean 都不作区分。spring-doc.cadn.net.cn

对于许多扩展容器功能,例如注解处理和 AOP 代理, BeanPostProcessor 扩展点至关重要。 如果您仅使用普通的 DefaultListableBeanFactory,则默认情况下不会检测并激活这些后处理器。这种情况可能会令人困惑,因为 您的 Bean 配置实际上没有任何问题。相反,在这种场景下, 需要通过额外的设置来完全引导容器。spring-doc.cadn.net.cn

下表列出了 BeanFactoryApplicationContext 接口及其实现所提供的功能。spring-doc.cadn.net.cn

表1. 功能矩阵
特性 BeanFactory ApplicationContext

Bean 的实例化/装配spring-doc.cadn.net.cn

是的spring-doc.cadn.net.cn

是的spring-doc.cadn.net.cn

集成的生命周期管理spring-doc.cadn.net.cn

Nospring-doc.cadn.net.cn

是的spring-doc.cadn.net.cn

自动注册 BeanPostProcessorspring-doc.cadn.net.cn

Nospring-doc.cadn.net.cn

是的spring-doc.cadn.net.cn

自动注册 BeanFactoryPostProcessorspring-doc.cadn.net.cn

Nospring-doc.cadn.net.cn

是的spring-doc.cadn.net.cn

便捷的 MessageSource 访问(用于国际化)spring-doc.cadn.net.cn

Nospring-doc.cadn.net.cn

是的spring-doc.cadn.net.cn

内置的ApplicationEvent发布机制spring-doc.cadn.net.cn

Nospring-doc.cadn.net.cn

是的spring-doc.cadn.net.cn

要显式地向 DefaultListableBeanFactory 注册一个 Bean 后置处理器, 你需要以编程方式调用 addBeanPostProcessor,如下例所示:spring-doc.cadn.net.cn

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 方法,如下例所示:spring-doc.cadn.net.cn

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 实例来扩展容器功能时更是如此。spring-doc.cadn.net.cn

AnnotationConfigApplicationContext 已注册了所有通用的注解后置处理器,并可通过配置注解(例如 @EnableTransactionManagement)在底层引入额外的后置处理器。 在 Spring 基于注解的配置模型这一抽象层级上,Bean 后置处理器的概念仅仅成为容器内部的一个实现细节。spring-doc.cadn.net.cn