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 核心容器的主要入口,用于所有常见的目的:加载配置文件、触发 classpath 扫描、以编程方式注册 Bean 定义和注解类,以及(从 5.0 开始)注册功能性 Bean 定义。
因为 ApplicationContext 包括 BeanFactory 的所有功能,所以通常推荐使用它而不是普通的 BeanFactory,除非是需要完全控制 Bean 处理的情况。在 ApplicationContext 中(如 GenericApplicationContext 的实现),通过惯例(即通过 bean 名称或 bean 类型—特别是后置处理器)来检测几种 bean,而普通的 DefaultListableBeanFactory 对任何特殊的 bean 都不了解。
对于许多扩展的容器功能,如注解处理和 AOP 代理,BeanPostProcessor 扩展点是必不可少的。如果你只使用普通的 DefaultListableBeanFactory,这样的后置处理器就不会被检测到并默认激活。这种情况可能会让人困惑,因为你的 bean 配置实际上没有任何问题。相反,在这种情况下,容器需要通过额外的设置来完全引导。
下表列出了 BeanFactory 和 ApplicationContext 接口和实现所提供的功能:
功能 | BeanFactory | ApplicationContext |
---|---|---|
Bean 的实例化/装配 | Yes | Yes |
综合生命周期管理 | No | Yes |
自动注册 BeanPostProcessor | No | Yes |
自动注册 BeanFactoryPostProcessor | No | Yes |
方便的 MessageSource 访问(用于国际化)。 | No | Yes |
内置的 ApplicationEvent 发布机制 | No | Yes |
要在 DefaultListableBeanFactory 中显式地注册一个 bean 后置处理器,你需要以编程方式调用 addBeanPostProcessor,如下例所示:
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// 用 Bean 定义来填充工厂
// 现在注册任何需要的 BeanPostProcessor 实例
factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
factory.addBeanPostProcessor(new MyBeanPostProcessor());
// 现在开始使用工厂
要将 BeanFactoryPostProcessor 应用于普通的 DefaultListableBeanFactory,你需要调用其 postProcessBeanFactory 方法,如下例所示:
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));
// 从属性文件中引入一些属性值
PropertySourcesPlaceholderConfigurer cfg = new PropertySourcesPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));
// 现在实际进行替换
cfg.postProcessBeanFactory(factory);
在这两种情况下,显式注册步骤都很不方便,这就是为什么在 Spring 支持的应用程序中,各种 ApplicationContext 变体比普通的 DefaultListableBeanFactory 更受欢迎,特别是在典型的企业设置中依靠 BeanFactoryPostProcessor 和 BeanPostProcessor 实例来扩展容器功能。
:::info AnnotationConfigApplicationContext 注册了所有常见的注解后处理器,并且可以通过配置注解引入额外的处理器,例如 @EnableTransactionManagement。在 Spring 基于注解的配置模型的抽象层面上, bean 后处理器的概念仅仅是一个内部容器的细节。 :::