BeanFactory API
BeanFactory API
BeanFactory API 为 Spring 的 IoC(控制反转)功能提供了基础。其具体的接口契约主要用于与 Spring 的其他部分及相关第三方框架的集成,而其 DefaultListableBeanFactory 实现则是更高级别的 GenericApplicationContext 容器中的关键委托组件。
BeanFactory 及相关接口(如 BeanFactoryAware、InitializingBean、DisposableBean)是其他框架组件的重要集成点。由于不需要任何注解甚至反射,它们允许容器与其组件之间进行非常高效的交互。应用级别的 Bean 可以使用相同的回调接口,但通常更倾向于使用声明式的依赖注入,无论是通过注解还是通过编程配置来实现。
请注意,核心的BeanFactory API级别及其DefaultListableBeanFactory实现并不对配置格式或将要使用的任何组件注解做出任何假设。所有这些扩展功能都是通过插件(如XmlBeanDefinitionReader和AutowiredAnnotationBeanPostProcessor)实现的,并且它们都操作作为核心元数据表示的共享BeanDefinition对象。这就是Spring容器如此灵活和可扩展的本质所在。
BeanFactory还是ApplicationContext?
本节解释了BeanFactory和ApplicationContext容器级别之间的差异,以及对启动(bootstrapping)过程的影响。
除非你有充分的理由不这样做,否则你应该使用ApplicationContext。GenericApplicationContext及其子类AnnotationConfigApplicationContext是用于自定义启动(bootstrapping)的常见实现。这些是进入Spring核心容器的主要入口点,可用于所有常见场景:加载配置文件、触发类路径扫描(classpath scan)、以编程方式注册bean定义和带注解的类,以及(从Spring 5.0开始)注册函数型bean定义(functional bean definitions)。
由于ApplicationContext包含了BeanFactory的所有功能,因此通常建议使用ApplicationContext而不是普通的BeanFactory,除非在需要完全控制bean处理流程的场景下。在ApplicationContext(例如GenericApplicationContext实现)中,可以通过约定来检测几种类型的bean(即通过bean名称或bean类型来识别,特别是后处理器),而普通的DefaultListableBeanFactory则对任何特殊的bean都不了解(即不具备这种识别能力)。
对于许多扩展的容器功能,如注释处理和AOP代理,BeanPostProcessor扩展点是必不可少的。如果你只使用普通的DefaultListableBeanFactory,那么这些后处理器默认情况下不会被检测到或激活。这种情况可能会令人困惑,因为实际上你的bean配置并没有问题。相反,在这种情况下,需要通过额外的设置来完全启动容器。
下表列出了BeanFactory和ApplicationContext接口及其实现所提供的功能。
表1. 特征矩阵
| 特性 | BeanFactory | ApplicationContext |
|---|---|---|
| Bean实例化/连接 | 是 | 是 |
| 集成生命周期管理 | 否 | 是 |
自动注册BeanPostProcessor | 否 | 是 |
自动注册BeanFactoryPostProcessor | 否 | 是 |
便捷的MessageSource访问(用于国际化) | 否 | 是 |
内置的ApplicationEvent发布机制 | 否 | 是 |
要显式地向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。尤其是在典型的企业环境中,当需要依赖BeanFactoryPostProcessor和BeanPostProcessor实例来扩展容器的功能时,这种偏好更为明显。
AnnotationConfigApplicationContext 已注册了所有常见的注解后处理器,并且可以通过配置注解(如 @EnableTransactionManagement)在内部引入额外的后处理器。在 Spring 基于注解的配置模型的抽象层面上,bean 后处理器的概念就仅仅变成了容器内部的细节而已。