我们在BeanFactoryPostProcessor
的doc中有这么一句:
/*
*
* <p>See PropertyResourceConfigurer and
* its concrete implementations
* for out-of-the-box solutions
* that address such configuration needs.
*/
我们点进PropertyResourceConfigurer
。
查看doc:
/**
* Allows for configuration of individual
* bean property values from a property resource,
* i.e. a properties file. Useful for
* custom config files targeted at system
* administrators that override bean properties
* configured in the application context.
*/
它是用来解析配置文件的信息的。
* <p>Two concrete implementations are provided in the distribution:
* <ul>
* <li>{@link PropertyOverrideConfigurer} for "beanName.property=value" style overriding
* (<i>pushing</i> values from a properties file into bean definitions)
* <li>{@link PropertyPlaceholderConfigurer} for replacing "${...}" placeholders
* (<i>pulling</i> values from a properties file into bean definitions)
* </ul>
* /
它有两个实现类,我们将用后者PropertyPlaceholderConfigurer
来演示如何读取配置文件的信息。这里取值的方式是常用SpEl表达式${...}
。
xml配置:
我们沿用Restaurant类。
<!--this configuration is for the TestPropertyPlaceholderConfigurerXml class-->
<bean id="restaurantBean" class="com.ocean.testBeanFactoryPostProcessor.Restaurant">
<property name="welcome" value="${customWelcome}"></property>
</bean>
<bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:restaurant.properties"></property>
</bean>
我们在resources
目录下建restaurant.properties
文件,内容是:
customWelcome='this welcome is from restaurant.properties'
测试:
public class TestPropertyPlaceholderConfigurerXml {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext
= new ClassPathXmlApplicationContext("factory-example.xml");
Restaurant restaurantBean = (Restaurant) applicationContext.getBean("restaurantBean");
restaurantBean.printWelcome();
}
}
打印出的信息是:
'this welcome is from restaurant.properties'
说明PropertyPlaceholderConfigurer
取值成功了。
Annotation配置:
把xml配置的内容注释掉。
@Configuration
@PropertySource(value = "classpath:restaurant.properties")
public class ConfigurationClass {
@Value("${customWelcome}")
private String welcome;
@Bean(value = "jack-restaurant")
public Restaurant restaurant(){
Restaurant restaurant = new Restaurant();
restaurant.setWelcome(welcome);
return restaurant;
}
@Bean
public static PropertyPlaceholderConfigurer propertyPlaceholderConfigurer(){
return new PropertyPlaceholderConfigurer();
}
}
注解配置的PropertyPlaceholderConfigurer
需要配合着@PropertySource
注解来使用。
注入PropertyPlaceholderConfigurer
的时候,我用了static
关键字,是希望它最早被注入。
测试:
public class TestPropertyPlaceholderConfigurerAnnotation {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext
= new AnnotationConfigApplicationContext(ConfigurationClass.class);
Restaurant restaurant = applicationContext.getBean("jack-restaurant", Restaurant.class);
restaurant.printWelcome();
}
}
此时报错了:
Could not resolve placeholder 'customWelcome' in value "${customWelcome}"
代码肯定没问题。
我们猜想,是不是PropertyPlaceholderConfigurer
在读取到配置文件的信息之前,@Value("${customWelcome}")
已经去取值了。
查看PropertyPlaceholderConfigurer
的文档:
<p>As of Spring 3.1,
{@link org.springframework.context.support.
PropertySourcesPlaceholderConfigurer
* PropertySourcesPlaceholderConfigurer}
* should be used preferentially over
* this implementation; it is
* more flexible through taking advantage of
* the {@link org.springframework.core.env.Environment}
* and
* {@link org.springframework.core.env.PropertySource}
* mechanisms also made available in Spring 3.1.
spring3.1之后,PropertySourcesPlaceholderConfigurer
优先于PropertySourcesPlaceholderConfigurer
加载。
于是我们注入PropertySourcesPlaceholderConfigurer
:
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(){
return new PropertySourcesPlaceholderConfigurer();
}
再次测试,通过。