来看一个Bean定义档的实际例子:
beans-config.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"
- "http://www.springframework.org/dtd/spring-beans.dtd">
- <beans>
- <bean id="configBean"
- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location">
- <value>hello.properties</value>
- </property>
- </bean>
- <bean id="helloBean" class="onlyfun.caterpillar.HelloBean">
- <property name="helloWord">
- <value>${onlyfun.caterpillar.helloWord}</value>
- </property>
- </bean>
- </beans>
假设在helloBean中有许多依赖注入的属性,这些都是比较不常变动的属性,而其中helloWord会经常变动,可以透过hello.properties来简单的设定,而这个资讯已设定在configBean的location属性中:
hello.properties
- onlyfun.caterpillar.helloWord=Welcome!
在helloBean的helloWord属性中,${onlyfun.caterpillar.helloWord}将会被hello.properties的helloWord所取代。
如果有多个.properties档案,则可以透过locations属性来设定,例如:
beans-config.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN"
- "http://www.springframework.org/dtd/spring-beans.dtd">
- <beans>
- <bean id="configBean"
- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations">
- <list> <value>hello.properties</value>
- <value>welcome.properties</value>
- <value>other.properties</value>
- </list>
- </property> </bean>
- <bean id="helloBean" class="onlyfun.caterpillar.HelloBean">
- <property name="helloWord">
- <value>${onlyfun.caterpillar.helloWord}</value>
- </property>
- ...
- </bean>
- </beans>
PropertyPlaceholderConfigurer类就是bean factory post-processor的一种,它的作用是一个资源属性的配置器,能够将BeanFactory的里定义的内容放在一个以.propertis后缀的文件中。
例如---spring-context.xml----
- <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="locations">
- <list>
- <value>/WEB-INF/jdbc.properties</value>
- </list>
- </property>
- </bean>
- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
- <property name="driverClassName"><value>${driver}</value></property>
- <property name="url"><value>jdbc:${dbname}</value></property>
- </bean>
而实际的jdbc.propertis文件是
jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root
而jdbc.propertis是怎样引用的呢: 将上边一段配置注册在web.xml中就可以了
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>/WEB-INF/spring-context.xml</param-value>
- </context-param> 当然,不要忘了spring的监听器注册
- <listener>
- <listener-class>
- org.springframework.web.context.ContextLoaderListener
- </listener-class>
- </listener>
这样,一个简单的数据源就设置完毕了。
实际上,PropertyPlaceholderConfigurer起的作用就是将占位符指向的数据库配置信息放在bean中定义
的工具。
1、一个简单的Demo
1.1、创建conf.xml
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id= "propertyConfigurer" class= "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!--
使用location属性定义单个配置文件
<property name= "location">
<value>classpath:/com/zsw/config/jdbc.properties</value>
</property>
-->
<!-- 使用locations属性定义多个配置文件 -->
<property name= "locations">
<list>
<value>classpath:/com/zsw/config/jdbc.properties</value>
</list>
</property>
</bean>
<bean id= "dataSource" class= "org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name= "url">
<value>${database.url}</value>
</property>
<property name= "driverClassName">
<value>${database.driver}</value>
</property>
<property name= "username">
<value>${database.user}</value>
</property>
<property name= "password">
<value>${database.password}</value>
</property>
</bean>
</beans>
1.2.创建jdbc.properties文件
database.url=jdbc:mysql: //localhost:3306/right?useUnicode=true&autoReconnect=true&characterEncoding=UTF-8
database.user=root
database.password=root
jdbc.pool.c3p0.acquire_increment=2
jdbc.pool.c3p0.max_size=20
jdbc.pool.c3p0.min_size=2
jdbc.pool.c3p0.preferred_test_query='SELECT 1'
jdbc.pool.c3p0.idle_connection_test_period=18000
jdbc.pool.c3p0.max_idle_time=25000
1.3.创建Config.java
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.FileSystemResource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
public class Config {
public static void main( String[] args) {
XmlBeanFactory factory = new XmlBeanFactory( new FileSystemResource( "src/com/zsw/config/conf.xml"));
// 如果要在BeanFactory中使用,bean factory post-processor必须手动运行:
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setLocation( new FileSystemResource( "src/com/zsw/config/jdbc.properties"));
cfg.postProcessBeanFactory(factory);
DriverManagerDataSource dataSource = (DriverManagerDataSource) factory.getBean( "dataSource");
// System.out.println(dataSource.getDriverClassName());
System.out.println(dataSource.getUsername());
// 注意,ApplicationContext能够自动辨认和应用在其上部署的实现了BeanFactoryPostProcessor的bean。这就意味着,当使用ApplicationContext的时候应用PropertyPlaceholderConfigurer会非常的方便。由于这个原因,建议想要使用这个或者其他bean
// factory postprocessor的用户使用ApplicationContext代替BeanFactroy。
ApplicationContext context = new ClassPathXmlApplicationContext( "com/zsw/config/conf.xml");
DriverManagerDataSource dataSource2 = (DriverManagerDataSource) context.getBean( "dataSource");
System.out.println(dataSource2.getUsername());
}
}
2.Spring中PropertyPlaceholderConfigurer多种配置方式
2.1配置单个Properties文件
<
bean id=
"propertyConfigurerForAnalysis"
class=
"org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
>
<
property name=
"location"
>
<
value>classpath:/spring/include/dbQuery.properties<
/value>
<
/property>
<
/bean>
< property name= "location" >
< value>classpath:/spring/include/dbQuery.properties< /value>
< /property>
< /bean>
其中classpath是引用src目录下的文件写法。
2.2 当存在多个Properties文件时,配置就需使用locations了:
< bean id= "propertyConfigurer" class= "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" > < property name= "locations" > < list> < value>classpath:/spring/include/jdbc-parms.properties< /value> < value>classpath:/spring/include/base-config.properties< /value> < /list> < /property> < /bean>
2.3、接下来我们要使用多个PropertyPlaceholderConfigurer来分散配置,达到整合多工程下的多个分散的Properties 文件,其配置如下:
<property name= "order" value= "1" />
<property name= "ignoreUnresolvablePlaceholders" value= "true" />
<property name= "location">
<value>classpath:/spring/include/dbQuery.properties</value>
</property>
</bean>
< property name= "order" value= "2" />
< property name= "ignoreUnresolvablePlaceholders" value= "true" />
< property name= "locations" >
< list>
< value>classpath:/spring/include/jdbc-parms.properties< /value>
< value>classpath:/spring/include/base-config.properties< /value>
< /list>
< /property>
< /bean>
其中order属性代表其加载顺序,而ignoreUnresolvablePlaceholders为是否忽略不可解析的 Placeholder,如配置了多个PropertyPlaceholderConfigurer,则需设置为true
2,将property配置文件与工程分离(独立到服务器中)
为什么想到要这样做呢?
这是在实际开发部署中,每次将工程打包部署到服务器,都需要在服务器端修改工程的配置项(如数据源等),感觉很麻烦。
如果工程优先读取放置在服务器上的配置文件,没有此配置文件才从工程目录里面读取,那样就可以将只在服务器存放一份配置文件并修改成与服务器运行环境一致,今后部署即可不用每次都修改工程配置文件了。
2.1 做法:
刚才我们在第1点添加了一个propertyConfigurer,现将其改名为“propertyConfigurer2”,并添加一个“propertyConfigurer1”,两者配置为:
- <bean id="propertyConfigurer1"
- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="order" value="1"/>
- <property name="ignoreResourceNotFound" value="true"/>
- <property name="ignoreUnresolvablePlaceholders" value="true" />
- <property name="location" value="file:C:/tempSys/config/global-config-file.properties"/>
- </bean>
- <bean id="propertyConfigurer2"
- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="order" value="2"/>
- <property name="ignoreUnresolvablePlaceholders" value="true" />
- <property name="location" value="classpath:global-config-file.properties"/>
- </bean>
order属性表示加载顺序,这种配置表示先加载propertyConfigurer1,在加载propertyConfigurer2,两者配置文件中有同样的参数,后加载的参数不会覆盖先加载的。
propertyConfigurer1需要添加一个 <property name="ignoreResourceNotFound" value="true"/>属性,表示当找不到这个配置文件时,则跳过,这样就不会抛出FileNotFoundException了。
这样配置之后,工程会在启动时,首先检查C:/tempSys/config/global-config-file.properties是否存在,如果存在则加载器配置,随后再加载项目目录下的global-config-file.properties;如果不存在,则直接加载项目目录下的global-config-file.properties。
这样做不单可将配置与开发环境分离出来,避免每次部署时繁琐的配置修改工作。同时这也提高了系统部署时的安全性,比如,实际运行的正式数据库账户密码信息将是十分机密的信息,由运维人员保管维护,可能对开发人员都不能公开(开发人员只知道开发测试数据库的信息),将这些信息直接配置在服务器上,服务器也由运维人员进行管理,这样可以减少机密信息的知晓人群,提高安全性。