问题
I have a custom ApplicationContext class where I'm trying to programmatically load a PropertyPlaceholderConfigurer, then use the placeholders in my XML config file.
I've tried three different approaches so far, and each time I get an error like this:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named '${domain}.testId' is defined
What I am doing wrong?
Context class
public class MyApplicationContext extends GenericApplicationContext {
public MyApplicationContext (String... locations) throws IOException {
// method one
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this);
scanner.scan("com.my.package");
// method two
new MyPropertyPlaceholderConfigurer().postProcessBeanFactory(getBeanFactory());
// method three
getBeanFactory().registerSingleton("propertyPlaceholderConfigurer", new MyPropertyPlaceholderConfigurer());
// load XML config files
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(this);
for (String location : locations) {
xmlReader.loadBeanDefinitions(location);
}
}
}
XML
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="test.testId" class="java.lang.String">
<constructor-arg value="this is the test value" />
</bean>
<bean id="prod.testId" class="java.lang.String">
<constructor-arg value="this is the prod value" />
</bean>
<alias name="${domain}.testId" alias="testId" />
</beans>
Usage
MyApplicationContext context = new MyApplicationContext(
new String[] { "test.xml" });
Assert.assertEquals("this is the test value", context.getBean("testId"));
回答1:
I appreciate the answers on how to define the bean, but it turns out the problem was much simpler. I was loading the bean just fine, but I wasn't properly initializing my context after loading all the beans. A simple call to refresh() did the trick.
MyApplicationContext context = new MyApplicationContext(
new String[] { "test.xml" });
context.refresh(); // this runs BeanFactoryPostProcessors like
// MyPropertyPlaceholderConfigurer, among other things
Assert.assertEquals("this is the test value", context.getBean("testId"));
回答2:
If you just want to use your own custom MyPropertyPlaceholderConfigurer
(assuming it extends PropertyPlaceholderConfigurer
, then all you need to do is to put it as a bean
in your application context, it'll do all the rest for you:
<bean class="my.pkg.MyPropertyPlaceholderConfigurer" />
回答3:
This is standard way how make your properties accessible in configuration file.
<util:list id="locations">
<value>classpath:appconfig.properties</value>
<value>classpath:jdbc.properties</value>
</util:list>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:ignoreResourceNotFound="true"
p:locations-ref="locations" />
<!-- bean that uses properties -->
<bean id="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource"
p:driverClass="${jdbc.driver}"
p:jdbcUrl="${jdbc.url}"
p:user="${jdbc.user}"
p:password="${jdbc.pw}"
p:initialPoolSize="5"
p:minPoolSize="5"
p:maxPoolSize="50"
p:idleConnectionTestPeriod="5" />
Another quite useful way how to "inject" properties in your configuration file on ANY place is using maven: you use same syntax ${property-name}
but values are supplied earlier during maven build process - this is relevant part of maven configuration:
<properties>
<jdbc.url>jdbc:mysql://localhost:3306/dummyuserdb</jdbc.url>
<jdbc.user>root</jdbc.user>
<jdbc.pw>admin</jdbc.pw>
</properties>
and you have to include your spring's configuration directory in maven filtered resources:
<build>
<resources>
<resource>
<directory>${basedir}/src/main/webapp/WEB-INF/spring-config</directory>
<filtering>true</filtering>
</resource>
</resources>
Or if you prefer java configuration:
@Configuration
@PropertySource(value = "config/jdbc.properties")
public class BaseWebConfig {
@Autowired Environment env;
@Bean
public MyBean myBean() {
MyBean myBean = new MyBean();
String propertyValue = env.getProperty("my-property-name");
// do something with myBean and propertyValue
return myBean;
}
}
}
来源:https://stackoverflow.com/questions/15075434/propertyplaceholderconfigurer-not-loading-programmatically