从源代码分析Spring处理property-placeholder原理

一、如何在Spring中将属性文件配置内容加载到环境中

1.1、在Spring的XML配置文件中配置<context:property-placeholder/>,由于<context:property-placeholder/>命名空间为

http://www.springframework.org/schema/context,通过命名空间名与处理程序的映射关系(Sping中配置的关系在sping.handlers文件中),

找到处理器http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler

1.2、在ContextNamespaceHandler中的init()函数中注册了parser解析器this.registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());

1.3、调用PropertyPlaceholderBeanDefinitionParser.parse()函数开始解析XML中配置的属性

1.4、在PropertyPlaceholderBeanDefinitionParser.parse()函数中调用了AbstractSingleBeanDefinitionParser.parseInternal()函数构建

构建内部BeanDefinition,最后调用了AbstractPropertyLoadingBeanDefinitionParser.doParse()函数解析property-placeholder自定义的属性

1.5、最后将构建好的BeanDefinition注册到BeanDefinitionRegistry注册中心中供Spring上下文使用


二、如何使用加载到环境中的配置

2.1、Spring通过BeanFactoryProcessor进行扩展,Spring提供了PropertyPlaceholderConfigurer(其实现了BeanFactoryPostProcessor)

在Bean创建前将占位符使用配置文件中的配置值替换

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" 
        init-method="init" destroy-method="close">
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>

</bean>

或者

@Value("${spring_only}")

private String springOnly;

2.2、通过两种方式注入

Bean方式:

单个配置文件

<bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="location">
     <value>conf/sqlmap/jdbc.properties</value>
   </property>
    <property name="fileEncoding">
      <value>UTF-8</value>
    </property>
</bean>
多个配置文件
<bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
    <property name="locations">
        <list>
            <value>/WEB-INF/mail.properties</value>  
            <value>classpath: conf/sqlmap/jdbc.properties</value>//注意这两种value值的写法
     </list>
    </property>

</bean>

标签方式:

<context:property-placeholder location="classpath*:/WEB-INF/mail.properties" />

今天一个问题困扰了我一下午,因此必须记录下来

PropertyPlaceholderConfigurer类中的location、locations、localProperties分别为 Resource、Resource[]、Properties[]类型,

而XML中指定属性值时却是字符串类型,一直都不知道Spring在什么时候、通过哪种机制处理转换的(将字符串转换成Resource、Resource[]、Properties[])

研究了很久发现Spring提供了一些系统的属性编辑器(超类为PropertyEditorSupport),Spring在解析和赋值property时,会调用对应的编辑器处理

,且Spring会默认依据property的类型找对应的编辑器。比如Resource有对应的编辑器ResourceEditor,会将字符串值转换处理为Resource、Resource[]。

若想要改变默认的PropertyEditor,可以添加自定义的来覆盖它。在添加时可以使用一个自动检测的机制:也就是需要遵照一定的规则

具体的规则是:PropertyEditor类和标准的 JavaBeans在同一个包下,并且他们PropertyEditor的类名是JavaBeans的类名加上“Editor”,比如:

[java]  view plain  copy
  1. public class ExoticTypeEditor extends PropertyEditorSupport {  
  2.     public void setAsText(String text) {  
  3.         setValue(new ExoticType(text.toUpperCase()));  
  4.     }  
  5. }  

可以看到这个PropertyEditor就是遵照了以上的命名规则,并且和ExoticType放在同一个包中,所以无需额外的配置就可以得到下面的输出:

ANAMEFOREXOTICTYPE


那么若没有符合以上规则的话,怎么办呢?可以通过org.springframework.beans.factory.config.CustomEditorConfigurer这个Bean来注册

为这个Bean配置customEditors属性,该属性是一个Map,将我们需要注册的PropertyEditors都注入到这个Map里就可以了:

[html]  view plain  copy
  1. <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">  
  2.     <property name="customEditors">  
  3.         <map>  
  4.             <entry key="document.six.test.ExoticType" value="document.six.test.ExoticType2Editor" />  
  5.         </map>  
  6.     </property>  
  7. </bean>  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值