1.16 BeanFactory

BeanFactory API为Spring的IOC功能提供了基础。其特定的契约主要用于与Spring和相关第三方框架的其他部分集成,其默认的ListableBeanFactory实现是更高级别GenericApplicationContext容器中的关键委托。

BeanFactory和相关接口(如BeanFactoryAware、InitializingBean、DisposableBean)是其他框架组件的重要集成点。通过不需要任何注解甚至反射,它们允许容器及其组件之间非常有效的交互。应用程序级bean可以使用相同的回调接口,但通常更倾向于通过注解或编程配置进行声明性依赖项注入。

请注意,核心BeanFactory API级别及其DefaultListableBeanFactory实现不会使用使用配置格式或任何组件注解。所有这些风格都通过扩展(如xmlbeanDefinitionReader和autowiredAnnotationBeanPostProcessor)传入,并作为核心元数据表示对共享BeanDefinition对象进行操作。这就是使Spring容器如此灵活和可扩展的本质所在。

1.16.1 BeanFactory 还是 ApplicationContext ?

本节解释BeanFactory和ApplicationContext容器级别之间的差异以及引导的含义。

除非有充分的理由不这样做,否则应该使用ApplicationContext,将GenericApplicationContext及其子类AnnotationConfigApplicationContext作为自定义引导的常见实现。这些是Spring核心容器的主要入口点,用于所有常见用途:加载配置文件、触发类路径扫描、以编程方式注册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的post-processor, 你需要在程序中调用addBeanPostProcessor,如下:

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

要应用BeanFactoryPostProcessor到普通的DefaultListableBeanFactory,你需要调用postProcessBeanFactory, 如下:

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));
// bring in some property values from a Properties file
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));
// now actually do the replacement
cfg.postProcessBeanFactory(factory);

在这两种情况下,显式注册步骤都不方便,这就是为什么在支持Spring的应用程序中,各种ApplicationContext变量比普通的defaultListableBeanFactory更受欢迎,特别是在典型企业应用中,依赖BeanFactoryPostProcessor和BeanPostProcessor实例实现扩展容器功能时。

AnnotationConfigApplicationContext注册了所有常见的注解后处理程序,并可以通过配置注解(如@EnableTransactionManagement)将其他处理程序置于覆盖范围内。在Spring基于注解的配置模型的抽象级别上,bean后处理器的概念变成了一个更内部的容器细节。