Skip to content

Spring提供了一种叫做BeanFactoryPostProcessor的容器扩展机制。该机制允许我们在容器实 例化相应对象之前,对注册到容器的BeanDefinition所保存的信息做相应的修改。这就相当于在容 器实现的第一阶段最后加入一道工序,让我们对最终的BeanDefinition做一些额外的操作,比如修改其中bean定义的某些属性,为bean定义增加其他信息等。

如果要自定义实现BeanFactoryPostProcessor,通常我们需要实org.springframework. beans.factory.config.BeanFactoryPostProcessor接口。同时,因为一个容器可能拥有多个BeanFactoryPostProcessor,这个时候可能需要实现类同时实现Spring的org.springframework.core. Ordered接口,以保证各个BeanFactoryPostProcessor可以按照预先设定的顺序执行(如果顺序紧 要的话)。但是,因为Spring已经提供了几个现成的BeanFactoryPostProcessor实现类,所以,大多时候,我们很少自己去实现某个BeanFactoryPostProcessor。其中,org.springframework.beans. factory.config.PropertyPlaceholderConfigurer和org.springframework.beans.factory. config.Property OverrideConfigurer是两个比较常用的BeanFactoryPostProcessor。另外,为了处理配置文件中的数据类型与真正的业务对象所定义的数据类型转换,Spring还允许我们通过 org.springframework.beans.factory.config.CustomEditorConfigurer来注册自定义的PropertyEditor以补助容器中默认的PropertyEditor。可以参考BeanFactoryPostProcessor的Javadoc来了解更多其实现子类的情况。

对于BeanFactory来说,我们需要用手动方式应用所有的BeanFactoryPostProcessor

对于ApplicationContext来说,情况看起来要好得多。因为ApplicationContext会自动识别配 置文件中的BeanFactoryPostProcessor并应用它,所以,相对于BeanFactory,在ApplicationContext 中加载并应用BeanFactoryPostProcessor,仅需要在XML配置文件中将这些BeanFactoryPostProcessor简单配置一下即可。

1、PropertyPlaceholderConfigurer:

通常情况下,我们不想将类似于系统管理相关的信息同业务对象相关的配置信息混杂到XML配置 文件中,以免部署或者维护期间因为改动繁杂的XML配置文件而出现问题。我们会将一些数据库连接 信息、邮件服务器等相关信息单独配置到一个properties文件中,这样,如果因系统资源变动的话,只 需要关注这些简单properties配置文件即可。PropertyPlaceholderConfigurer允许我们在XML配置文件中使用占位符(PlaceHolder), 并将这些占位符所代表的资源单独配置到简单的properties文件中来加载。

基本机制就是之前所说的那样。当BeanFactory在第一阶段加载完成所有配置信息时,BeanFactory中保存的对象的属性信息还只是以占位符的形式存在,如${jdbc.url}、${jdbc.driver}。当 PropertyPlaceholderConfigurer作为BeanFactoryPostProcessor被应用时,它会使用properties 配置文件中的配置信息来替换相应BeanDefinition中占位符所表示的属性值。这样,当进入容器实 现的第二阶段实例化bean时,bean定义中的属性值就是最终替换完成的了。 PropertyPlaceholderConfigurer不单会从其配置的properties文件中加载配置项,同时还会检 查Java的System类中的Properties,可以通过setSystemPropertiesMode()或者setSystemPropertiesModeName()来控制是否加载或者覆盖System相应Properties的行为。PropertyPlaceholderConfigurer提供了SYSTEM_PROPERTIES_MODE_FALLBACK、SYSTEM_PROPERTIES_MODE_NEVER和SYSTEM_PROPERTIES_MODE_OVERRIDE三种模式。默认采用的是SYSTEM_PROPERTIES_ MODE_FALLBACK,即如果properties文件中找不到相应配置项,则到System的Properties中查找,我们还可以选择不检查System 的Properties或者覆盖它。

2、 CustomEditorConfigurer: 我们知道,不管对象是什么类型,也不管这些对象所声明的依赖对象是什么类型,通常都是通过 XML(或者properties甚至其他媒介)文件格式来配置这些对象类型。但XML所记载的,都是String类 型,即容器从XML格式的文件中读取的都是字符串形式,最终应用程序却是由各种类型的对象所构成。 要想完成这种由字符串到具体对象的转换(不管这个转换工作最终由谁来做),都需要这种转换规则 相关的信息,而CustomEditorConfigurer就是帮助我们传达类似信息的。

Spring内部通过JavaBean的PropertyEditor来帮助进行String类型到其他类型的转换工作。只要 为每种对象类型提供一个 PropertyEditor ,就可以根据该对象类型取得与其相对应的 PropertyEditor来做具体的类型转换。Spring容器内部在做具体的类型转换的时候,会采用JavaBean 框架内默认的PropertyEditor搜寻逻辑,从而继承了对原生类型以及java.lang.String.java.awt. Color和java.awt.Font等类型的转换支持。同时,Spring框架还提供了自身实现的一些PropertyEditor,这些PropertyEditor大部分都位于org.springframework. beans.propertyeditors包 下。

Released under the MIT License.