Spring 利用PropertyPlaceholderConfigurer占位符
1. PropertyPlaceholderConfigurer是个bean工厂后置处理器的实现,也就是 BeanFactoryPostProcessor接口的一个实现。PropertyPlaceholderConfigurer可以将上下文(配置文 件)中的属性值放在另一个单独的标准java Properties文件中去。在XML文件中用${key}替换指定的properties文件中的值。这样的话,只需要对properties文件进 行修改,而不用对xml配置文件进行修改。
要了解这个类首先要弄清楚一个概念:bean factory post-processor(bean工厂后置处理器)
官方解释是这样的:
A bean factory post-processor is a java class which implements the
org.springframework.beans.factory.config.BeanFactoryPostProcessor interface. It is executed manually (in the case of the BeanFactory) or automatically (in the case of the ApplicationContext) to apply changes of some sort to an entire BeanFactory, after it has been constructed.
我理解的意思是这样的:
1.1. 首先bean factory post-processor实现了org.springframework.beans.factory.config.BeanFactoryPostProcessor接口。
1.2. 在BeanFactory的情况下它被手动的执行。
1.3. 在ApplicationContext的条件下它会自动的执行。
1.4. 最关键的一点是,是在这个类的实例被构造出来之后,对整个BeanFactory进行修改。
那么PropertyPlaceholderConfigurer类就是bean factory post-processor的一种,它的作用是一个资源属性的配置器,能够将BeanFactory的里定义的内容放在一个.propertis的文件中。执行该后置处理器时,会用.propertis文件中的值替换掉配置当中的${key}。
2.在Spring中,使用PropertyPlaceholderConfigurer可以在XML配置文件中加入外部属性文件,当然也可以指定外部文件的编码,如:
<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>
3.譬如,jdbc.properties的内容为:
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost/mysqldb?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=round; jdbc.username=root jdbc.password=123456
4.那么在spring配置文件中,我们就可以这样写:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath: conf/sqlmap/jdbc.properties </value> </list> </property> </bean> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close"> <property name="driverClassName"value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}"/> <property name="password"value="${jdbc.password}" /> </bean>
5. 这样,一个简单的数据源就设置完毕了。可以看出:PropertyPlaceholderConfigurer起的作用就是将占位符指向的数据库配置信息放在bean中定义的工具。
6. 查看源代码,可以发现,locations属性定义在PropertyPlaceholderConfigurer的祖父类 PropertiesLoaderSupport中,而location只有 setter方法。类似于这样的配置,在spring的源程序中很常见的。
PropertyPlaceholderConfigurer如果在指定的Properties文件中找不到你想使用的属性,它还会在Java的System类属性中查找。
我们可以通过System.setProperty(key, value)或者java中通过-Dnamevalue来给Spring配置文件传递参数。
7、我们还可以使用注解的方式实现,如:<context:property-placeholder location="classpath:jdbc.properties" />,效果跟PropertyPlaceholderConfigurer是一样的。
如:
<context:property-placeholder location="classpath:/property/placeholder/value/abc.properties,classpath:/property/placeholder/value/app.properties" />
如果分开写成两个:
<context:property-placeholder location="classpath:/property/placeholder/value/abc.properties“ /> <context:property-placeholder location="classpath:/property/placeholder/value/app.properties" />
那么只会加载第一个,也就是abc.properties,app.properties会忽略。
或者注解方式:
@PropertySource("classpath:/property/placeholder/value/app.properties,classpath:/property/placeholder/value/app.properties")
public class PopularDisc implements CompactDisc {
......
}
8. 另外,如果是0配置的spring工程,不想使用任何xml文件,但是也想采用PropertyPlaceholderConfigurer,可以使用如下方法:
Resource r = new FileSystemResource(getClass().getResource("/app.properties").getPath()); PropertyPlaceholderConfigurer pphc = new PropertyPlaceholderConfigurer(); pphc.setLocation(r); context.addBeanFactoryPostProcessor(pphc); context.refresh();
或者使用
pphc.postProcessBeanFactory(context.getBeanFactory());
替代 context.addBeanFactoryPostProcessor(pphc);
不管使用两者当中的哪一个,都必须在context.refresh()之前调用。
如果像<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">的方式,使用@Configuration、@Bean获得PropertyPlaceholderConfigurer Bean的方式会报错。也就是不能像普通获得bean那样使用@Configuration、@Bean。
参考:
浅析Spring框架下PropertyPlaceholderConfigurer类