备注:此文部分来源于官网内容的翻译
BeanFactory
BeanFactory API提供了spring IOC容器的基础功能。它特殊的设计大多数被用于与spring其他的模块或者第三方的框架进行集成。DefaultListableBeanFactory是高层(high-level)API(GenericApplicationContext)的委托容器,即高层次的API(ApplicationContext),都拥有一个DefaultListableBeanFactory类型的字段,并将容器功能委托给它来实现。
BeanFactory和相关的接口(BeanFactoryAware, InitializingBean, DisposableBean)对spring其他组件来说,是很重要的集成点。不需要任何注解,这些集成点可以方便的让容器和容器中的组件进行交互。应用级别的beans可以使用这些集成点,不过建议用显示的配置来声明这些依赖。
底层的BeanFactory API及其实现DefaultListableBeanFactory,并没有固定死配置的格式。至于使用那种格式的配置,是通过扩展(XmlBeanDefinitionReader,AutowiredAnnotationBeanPostProcessor)来实现的,这两个扩展会将特定格式的配置解析成bean的定义(BeanDefinition),并存储到BeanFactory中,供后续实例化bean时使用。
BeanFactory or ApplicationContext?
一般情况应该优先使用ApplicationContext(GenericApplicationContext,AnnotationConfigApplicationContext),除非你有特殊需,ApplicationContext无法达成。ApplicationContext类初始化时,有以下主要阶段:加载配置文件,触发class path扫描,注册普通bean的定义,注册一些特殊的bean(比如实现了BeanPostProcessor接口的)
ApplicationContext拥有BeanFactory所有的功能,所以优先推荐使用ApplicationContext。除非有些场景,你想拥bean处理过程中完全的控制权。在ApplicationContext中,一些特殊的bean(spring自己设定好的,比如post-processors)会被检测到,并进行特定的处理,但是DefaultListableBeanFactory却没有这个机制。
许多扩展功能,比如一些特殊的注解,代理等,需要BeanPostProcessor的实现类来处理,如果你使用DefaultListableBeanFactory,这些功能默认是没有的。
下面的列表是两种接口的功能对比:
功能 BeanFactory | ApplicationContext |
---|---|
Bean实例化及依赖装配 | 有 |
bean生命周期管理 | 无 |
定制的BeanPostProcessor注册 | 无 |
定制的BeanFactoryPostProcessor | 无 |
便利的MessageSource访问 | 无 |
内置的ApplicationEvent时间机制 | 无 |
BeanPostProcessor
如果使用DefaultListableBeanFactory,你得自己编码添加自定义的post-processor。
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// 从配置中读取bean的定义
...
// 注册需要的BeanPostProcessor实例
factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
factory.addBeanPostProcessor(new MyBeanPostProcessor());
BeanFactoryPostProcessor
与BeanPostProcessor类似,如果使用DefaultListableBeanFactory,你得手工添加自定义的实现
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);