BeanFactory相关后置处理接口

1. PropertyPlaceholderConfigurer 和PropertyOverrideConfigurer

1.1 类的功能

PropertyPlaceholderConfigurer这个类是用于将外部指定properties文件中的变量值替换到配置文件中属性定义的占位符中。

PropertyOverrideConfigurer与PropertyPlaceholderConfigurer类似,该类将会用外部properties文件中的属性的值替换spring容器中指定bean中的指定属性的值。因此PropertyOverrideConfigurer的需要的properties文件格式必须按照以下格式:

beanName.propertyName=propertyValue

它与PropertyPlaceholderConfigurer的区别在于:

a. 不是通过占位符来进行匹配。

b. bean的property可以出现在配置之中也可以不出现。

1.2 类结构

在分析具体实现之前,先看类结构图:


1.2.1 PropertiesLoaderSupport:
该类用于对properties进行加载,它支持两种方式指定properties:

一种是通过properties属性在配置文件中通过<props></props>元素指定,这种方式称为local方式

一种是通过locations属性从外部properties或者xml文件中读取。

当然这两种方式可以同时存在,当出现同名冲突时,可以通过localOverride参数来指定那种方式中的同名配置起作用,false时,优先使用外部文件中的配置,true则相反,默认为false。

properties文件加载,PropertiesLoaderSupport会委托给DefaultPropertiesPersister来进行。

1.2.2 PropertyResourceConfigurer:
该类实现了PriorityOrdered和BeanFactoryPostProccessor接口,同时抽取了在属性置换或者占位符处理之前的共同逻辑,包括:

1.加载properties,并合并同名配置。

2.对properties的value进行转换,这里暴露了一个convertProperties()方法,便于子类扩展,子类可以通过覆盖该方法来进行一些特殊操作,譬如加密解密等。

3.提供processProperties()抽象接口用于子类扩展。

由于它实现了BeanFactoryPostProccessor接口,因此,可以知道它的执行时机是在beanFacotry创建完毕,且BeanDefinition加载完成之后就会执行。具体的位置在AbstractApplicationContext.refresh()->AbstarctApplicationContext.invokeBeanFactoryPostProcessors()中

1.2.3 PropertyPlaceholderConfigurer:
该类利用properties中指定的value替换占位符的内容。

通过分析可以知道,该类除了能够支持PropertiesLoaderSupport的两种方式加载properties外,还可以支持从JVM运行参数中加载properties.当然,对于名字冲突重名的情况,它提供了参数供选择:

SYSTEM_PROPERTIES_MODE_NEVER:不从System.getProperties中加载

SYSTEM_PROPERTIES_MODE_FALLBACK:若在前两种方式都无法解析的占位符,则尝试从System.getProperties()中加载。该参数下,System.getProperties()优先级最低。默认值为该值。

SYSTEM_PROPERTIES_MODE_OVERRIDE:优先从System.getProperties()中加载属性值。

另外,在spring 2.5版之后,对于占位符出现的位置可以是下面几处

<bean id="test" class="${beanClass}" parent="${parentName}" scope="${scope}" factory-bean="${factoryBeanName}" factory-method="${factoryMethod}">
<constructor-arg index="0"><value>${constructorValue}</value></constructor-arg>
<property name="p1">
<value>${propertyValue}</value>
</property>
</bean>

1.2.4 PropertyOverrideConfigurer
该类直接用指定properties中的值替换掉bean中属性值,它要求属性配置文件中的格式必须满足

beanName.propertyName=propertyValue

因此,它不需要像PropertyPlaceholderConfigurer一样显式指定占位符。它的处理逻辑也很简单,通过properties中指定的配置获取配置相对应的beanName,然后从beanFactory中得到BeanDefinition,然后用propertyValue替换名为propertyName的属性。

2 CustomEditorConfigurer

该类用于支持用户向beanFacotry中注册一些自定义的复杂类型转换器,用于将字符串转换为一些特殊类型的值。

2.1 类结构图:


类图中PropertyEditor是java.beans中定义的属性编辑器的通用接口。PropertyEditorSupport实现了该接口,并实现了一部分通用对逻辑。

PropertyEditorRegistrar定义了一个属性注册器(PropertyEditorRegistry)的管理器接口。用于管理多个PropertyEditorRegistry

PropertyEditorRegistry定义了一个属性注册器接口,用于管理多个PropertyEditor。

2.2 两种注册方式

CustomEditorConfigurer支持两种方式的自定义属性编辑器的注册。

一种是向CustomEditorConfigurer注册多个属性注册器管理器,当在不同情况下(如编写一个相应的注册器然后在多种情况下重用它)需要使用相同的属性编辑器时该接口特别有用。如:

<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
   <property name="propertyEditorRegistrars">
     <list>
       <bean class="mypackage.MyCustomDateEditorRegistrar"/>
       <bean class="mypackage.MyObjectEditorRegistrar"/>
     </list>
   </property>
 </bean>
另一种是直接向CustomEditorConfigurer添加多个属性编辑器PropertyEditor,如:
<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
   <property name="customEditors">
     <map>
       <entry key="java.util.Date" value="mypackage.MyCustomDateEditor"/>
       <entry key="mypackage.MyObject" value="mypackage.MyObjectEditor"/>
     </map>
   </property>
</bean>

需要注意的是,<entry>个格式必须满足key为转换的目标对象的class名,value是属性编辑器的类名(当然也支持编辑器的实例,但是高版本的spring已经不建议这么做)

由类结构图可以看出CustomEditorConfigurer实现了BeanFactoryPostProcessor,因此它的执行时机也是在beanFacotry创建完毕,且BeanDefinition加载完成之后就会执行。由于通过Ordered接口指定了LOWEST_PRECEDENCE,即最低级别的Order,它的执行顺序会相对靠后。

2.3 何时使用自定义PropertyEditor?

spring在创建bean实例过程中。具体讲来就是在创建BeanWrapperImpl实例后,spring会复制一份当前容器中注册的PropertyEditor到BeanWrapperImpl中,用于属性转换,具体请参考 spring bean实例化过程


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值