I have a bunch of Spring beans which are picked up from the classpath via annotations, e.g.
@Repository("personDao")
public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao {
// Implementation omitted
}
In the Spring XML file, there's a PropertyPlaceholderConfigurer defined:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
I want to inject one of the properties from app.properites into the bean shown above. I can't simply do something like
<bean class="com.example.PersonDaoImpl">
<property name="maxResults" value="${results.max}"/>
</bean>
Because PersonDaoImpl does not feature in the Spring XML file (it is picked up from the classpath via annotations). I've got as far as the following:
@Repository("personDao")
public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao {
@Resource(name = "propertyConfigurer")
protected void setProperties(PropertyPlaceholderConfigurer ppc) {
// Now how do I access results.max?
}
}
But it's not clear to me how I access the property I'm interested in from ppc
?
This question is related to
java
spring
dependency-injection
If you are stuck using Spring 2.5 you could define a bean for each of your properties and inject them using qualifiers. Like this:
<bean id="someFile" class="java.io.File">
<constructor-arg value="${someFile}"/>
</bean>
and
@Service
public class Thing
public Thing(@Qualifier("someFile") File someFile) {
...
Its not super readable but it gets the job done.
<context:property-placeholder ... />
is the XML equivalent to the PropertyPlaceholderConfigurer.
Example: applicationContext.xml
<context:property-placeholder location="classpath:test.properties"/>
Component class
private @Value("${propertyName}") String propertyField;
A possible solutions is to declare a second bean which reads from the same properties file:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
<util:properties id="appProperties" location="classpath:/WEB-INF/app.properties"/>
The bean named 'appProperties' is of type java.util.Properties and can be dependency injected using the @Resource attruibute shown above.
As mentioned @Value
does the job and it is quite flexible as you can have spring EL in it.
Here are some examples, which could be helpful:
//Build and array from comma separated parameters
//Like currency.codes.list=10,11,12,13
@Value("#{'${currency.codes.list}'.split(',')}")
private List<String> currencyTypes;
Another to get a set
from a list
//If you have a list of some objects like (List<BranchVO>)
//and the BranchVO has areaCode,cityCode,...
//You can easily make a set or areaCodes as below
@Value("#{BranchList.![areaCode]}")
private Set<String> areas;
You can also set values for primitive types.
@Value("${amount.limit}")
private int amountLimit;
You can call static methods:
@Value("#{T(foo.bar).isSecurityEnabled()}")
private boolean securityEnabled;
You can have logic
@Value("#{T(foo.bar).isSecurityEnabled() ? '${security.logo.path}' : '${default.logo.path}'}")
private String logoPath;
I need to have two properties files, one for production and an override for development (that will not be deployed).
To have both, a Properties Bean that can be autowired and a PropertyConfigurer, you can write:
<bean id="appProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:live.properties</value>
<value>classpath:development.properties</value>
</list>
</property>
</bean>
and reference the Properties Bean in the PropertyConfigurer
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="appProperties" />
</bean>
Autowiring Property Values into Spring Beans:
Most people know that you can use @Autowired to tell Spring to inject one object into another when it loads your application context. A lesser known nugget of information is that you can also use the @Value annotation to inject values from a property file into a bean’s attributes. see this post for more info...
new stuff in Spring 3.0 || autowiring bean values ||autowiring property values in spring
I need to have two properties files, one for production and an override for development (that will not be deployed).
To have both, a Properties Bean that can be autowired and a PropertyConfigurer, you can write:
<bean id="appProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:live.properties</value>
<value>classpath:development.properties</value>
</list>
</property>
</bean>
and reference the Properties Bean in the PropertyConfigurer
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="appProperties" />
</bean>
For me, it was @Lucky's answer, and specifically, the line
AutowiredFakaSource fakeDataSource = ctx.getBean(AutowiredFakaSource.class);
that fixed my problem. I have an ApplicationContext-based app running from the command-line, and judging by a number of the comments on SO, Spring wires up these differently to MVC-based apps.
I think it's most convenient way to inject properties into bean is setter method.
Example:
package org.some.beans;
public class MyBean {
Long id;
String name;
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Bean xml definition:
<bean id="Bean1" class="org.some.beans.MyBean">
<property name="id" value="1"/>
<property name="name" value="MyBean"/>
</bean>
For every named property
method setProperty(value)
will be invoked.
This way is especially helpful if you need more than one bean based on one implementation.
For example, if we define one more bean in xml:
<bean id="Bean2" class="org.some.beans.MyBean">
<property name="id" value="2"/>
<property name="name" value="EnotherBean"/>
</bean>
Then code like this:
MyBean b1 = appContext.getBean("Bean1");
System.out.println("Bean id = " + b1.getId() + " name = " + b1.getName());
MyBean b2 = appContext.getBean("Bean2");
System.out.println("Bean id = " + b2.getId() + " name = " + b2.getName());
Will print
Bean id = 1 name = MyBean
Bean id = 2 name = AnotherBean
So, in your case it should look like this:
@Repository("personDao")
public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao {
Long maxResults;
public void setMaxResults(Long maxResults) {
this.maxResults = maxResults;
}
// Now use maxResults value in your code, it will be injected on Bean creation
public void someMethod(Long results) {
if (results < maxResults) {
...
}
}
}
For me, it was @Lucky's answer, and specifically, the line
AutowiredFakaSource fakeDataSource = ctx.getBean(AutowiredFakaSource.class);
that fixed my problem. I have an ApplicationContext-based app running from the command-line, and judging by a number of the comments on SO, Spring wires up these differently to MVC-based apps.
Another alternative is to add the appProperties bean shown below:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
<bean id="appProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true"/>
<property name="properties">
<props>
<prop key="results.max">${results.max}</prop>
</props>
</property>
</bean>
When retrieved, this bean can be cast to a java.util.Properties
which will contain a property named results.max
whose value is read from app.properties
. Again, this bean can be dependency injected (as an instance of java.util.Properties) into any class via the @Resource annotation.
Personally, I prefer this solution (to the other I proposed), as you can limit exactly which properties are exposed by appProperties, and don't need to read app.properties twice.
Easiest way in Spring 5 is to use @ConfigurationProperties
here is example
https://mkyong.com/spring-boot/spring-boot-configurationproperties-example/
If you need more Flexibility for the configurations, try the Settings4jPlaceholderConfigurer: http://settings4j.sourceforge.net/currentrelease/configSpringPlaceholder.html
In our application we use:
The default order which key-value-Source is checked first, is described in:
http://settings4j.sourceforge.net/currentrelease/configDefault.html
It can be customized with a settings4j.xml (accurate to log4j.xml) in your classpath.
Let me know your opinion: [email protected]
with friendly regards,
Harald
I need to have two properties files, one for production and an override for development (that will not be deployed).
To have both, a Properties Bean that can be autowired and a PropertyConfigurer, you can write:
<bean id="appProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:live.properties</value>
<value>classpath:development.properties</value>
</list>
</property>
</bean>
and reference the Properties Bean in the PropertyConfigurer
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="appProperties" />
</bean>
Spring way:
private @Value("${propertyName}")
String propertyField;
is a new way to inject the value using Spring's "PropertyPlaceholderConfigurer" class. Another way is to call
java.util.Properties props = System.getProperties().getProperty("propertyName");
Note: For @Value, you can not use static propertyField, it should be non-static only, otherwise it returns null. To fix it a non static setter is created for the static field and @Value is applied above that setter.
I think it's most convenient way to inject properties into bean is setter method.
Example:
package org.some.beans;
public class MyBean {
Long id;
String name;
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Bean xml definition:
<bean id="Bean1" class="org.some.beans.MyBean">
<property name="id" value="1"/>
<property name="name" value="MyBean"/>
</bean>
For every named property
method setProperty(value)
will be invoked.
This way is especially helpful if you need more than one bean based on one implementation.
For example, if we define one more bean in xml:
<bean id="Bean2" class="org.some.beans.MyBean">
<property name="id" value="2"/>
<property name="name" value="EnotherBean"/>
</bean>
Then code like this:
MyBean b1 = appContext.getBean("Bean1");
System.out.println("Bean id = " + b1.getId() + " name = " + b1.getName());
MyBean b2 = appContext.getBean("Bean2");
System.out.println("Bean id = " + b2.getId() + " name = " + b2.getName());
Will print
Bean id = 1 name = MyBean
Bean id = 2 name = AnotherBean
So, in your case it should look like this:
@Repository("personDao")
public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao {
Long maxResults;
public void setMaxResults(Long maxResults) {
this.maxResults = maxResults;
}
// Now use maxResults value in your code, it will be injected on Bean creation
public void someMethod(Long results) {
if (results < maxResults) {
...
}
}
}
Personally I love this new way in Spring 3.0 from the docs:
private @Value("${propertyName}") String propertyField;
No getters or setters!
With the properties being loaded via the config:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:propertyFile.properties" name="propertiesBean"/>
To further my glee I can even control click on the EL expression in IntelliJ and it brings me to the property definition!
There's also the totally non xml version:
@PropertySource("classpath:propertyFile.properties")
public class AppConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
Before we get Spring 3 - which allows you to inject property constants directly into your beans using annotations - I wrote a sub-class of the PropertyPlaceholderConfigurer bean that does the same thing. So, you can mark up your property setters and Spring will autowire your properties into your beans like so:
@Property(key="property.key", defaultValue="default")
public void setProperty(String property) {
this.property = property;
}
The Annotation is as follows:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface Property {
String key();
String defaultValue() default "";
}
The PropertyAnnotationAndPlaceholderConfigurer is as follows:
public class PropertyAnnotationAndPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
private static Logger log = Logger.getLogger(PropertyAnnotationAndPlaceholderConfigurer.class);
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties properties) throws BeansException {
super.processProperties(beanFactory, properties);
for (String name : beanFactory.getBeanDefinitionNames()) {
MutablePropertyValues mpv = beanFactory.getBeanDefinition(name).getPropertyValues();
Class clazz = beanFactory.getType(name);
if(log.isDebugEnabled()) log.debug("Configuring properties for bean="+name+"["+clazz+"]");
if(clazz != null) {
for (PropertyDescriptor property : BeanUtils.getPropertyDescriptors(clazz)) {
Method setter = property.getWriteMethod();
Method getter = property.getReadMethod();
Property annotation = null;
if(setter != null && setter.isAnnotationPresent(Property.class)) {
annotation = setter.getAnnotation(Property.class);
} else if(setter != null && getter != null && getter.isAnnotationPresent(Property.class)) {
annotation = getter.getAnnotation(Property.class);
}
if(annotation != null) {
String value = resolvePlaceholder(annotation.key(), properties, SYSTEM_PROPERTIES_MODE_FALLBACK);
if(StringUtils.isEmpty(value)) {
value = annotation.defaultValue();
}
if(StringUtils.isEmpty(value)) {
throw new BeanConfigurationException("No such property=["+annotation.key()+"] found in properties.");
}
if(log.isDebugEnabled()) log.debug("setting property=["+clazz.getName()+"."+property.getName()+"] value=["+annotation.key()+"="+value+"]");
mpv.addPropertyValue(property.getName(), value);
}
}
for(Field field : clazz.getDeclaredFields()) {
if(log.isDebugEnabled()) log.debug("examining field=["+clazz.getName()+"."+field.getName()+"]");
if(field.isAnnotationPresent(Property.class)) {
Property annotation = field.getAnnotation(Property.class);
PropertyDescriptor property = BeanUtils.getPropertyDescriptor(clazz, field.getName());
if(property.getWriteMethod() == null) {
throw new BeanConfigurationException("setter for property=["+clazz.getName()+"."+field.getName()+"] not available.");
}
Object value = resolvePlaceholder(annotation.key(), properties, SYSTEM_PROPERTIES_MODE_FALLBACK);
if(value == null) {
value = annotation.defaultValue();
}
if(value == null) {
throw new BeanConfigurationException("No such property=["+annotation.key()+"] found in properties.");
}
if(log.isDebugEnabled()) log.debug("setting property=["+clazz.getName()+"."+field.getName()+"] value=["+annotation.key()+"="+value+"]");
mpv.addPropertyValue(property.getName(), value);
}
}
}
}
}
}
Feel free to modify to taste
Personally I love this new way in Spring 3.0 from the docs:
private @Value("${propertyName}") String propertyField;
No getters or setters!
With the properties being loaded via the config:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:propertyFile.properties" name="propertiesBean"/>
To further my glee I can even control click on the EL expression in IntelliJ and it brings me to the property definition!
There's also the totally non xml version:
@PropertySource("classpath:propertyFile.properties")
public class AppConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
Another alternative is to add the appProperties bean shown below:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
<bean id="appProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true"/>
<property name="properties">
<props>
<prop key="results.max">${results.max}</prop>
</props>
</property>
</bean>
When retrieved, this bean can be cast to a java.util.Properties
which will contain a property named results.max
whose value is read from app.properties
. Again, this bean can be dependency injected (as an instance of java.util.Properties) into any class via the @Resource annotation.
Personally, I prefer this solution (to the other I proposed), as you can limit exactly which properties are exposed by appProperties, and don't need to read app.properties twice.
Autowiring Property Values into Spring Beans:
Most people know that you can use @Autowired to tell Spring to inject one object into another when it loads your application context. A lesser known nugget of information is that you can also use the @Value annotation to inject values from a property file into a bean’s attributes. see this post for more info...
new stuff in Spring 3.0 || autowiring bean values ||autowiring property values in spring
If you need more Flexibility for the configurations, try the Settings4jPlaceholderConfigurer: http://settings4j.sourceforge.net/currentrelease/configSpringPlaceholder.html
In our application we use:
The default order which key-value-Source is checked first, is described in:
http://settings4j.sourceforge.net/currentrelease/configDefault.html
It can be customized with a settings4j.xml (accurate to log4j.xml) in your classpath.
Let me know your opinion: [email protected]
with friendly regards,
Harald
Another alternative is to add the appProperties bean shown below:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
<bean id="appProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true"/>
<property name="properties">
<props>
<prop key="results.max">${results.max}</prop>
</props>
</property>
</bean>
When retrieved, this bean can be cast to a java.util.Properties
which will contain a property named results.max
whose value is read from app.properties
. Again, this bean can be dependency injected (as an instance of java.util.Properties) into any class via the @Resource annotation.
Personally, I prefer this solution (to the other I proposed), as you can limit exactly which properties are exposed by appProperties, and don't need to read app.properties twice.
Spring way:
private @Value("${propertyName}")
String propertyField;
is a new way to inject the value using Spring's "PropertyPlaceholderConfigurer" class. Another way is to call
java.util.Properties props = System.getProperties().getProperty("propertyName");
Note: For @Value, you can not use static propertyField, it should be non-static only, otherwise it returns null. To fix it a non static setter is created for the static field and @Value is applied above that setter.
There is a new annotation @Value
in Spring 3.0.0M3. @Value
support not only #{...}
expressions but ${...}
placeholders as well
I need to have two properties files, one for production and an override for development (that will not be deployed).
To have both, a Properties Bean that can be autowired and a PropertyConfigurer, you can write:
<bean id="appProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:live.properties</value>
<value>classpath:development.properties</value>
</list>
</property>
</bean>
and reference the Properties Bean in the PropertyConfigurer
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="appProperties" />
</bean>
Use Spring's "PropertyPlaceholderConfigurer" class
A simple example showing property file read dynamically as bean's property
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/classes/config_properties/dev/database.properties</value>
</list>
</property>
</bean>
<bean id="devDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${dev.app.jdbc.driver}"/>
<property name="jdbcUrl" value="${dev.app.jdbc.url}"/>
<property name="user" value="${dev.app.jdbc.username}"/>
<property name="password" value="${dev.app.jdbc.password}"/>
<property name="acquireIncrement" value="3"/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="10"/>
<property name="maxStatementsPerConnection" value="11000"/>
<property name="numHelperThreads" value="8"/>
<property name="idleConnectionTestPeriod" value="300"/>
<property name="preferredTestQuery" value="SELECT 0"/>
</bean>
Property File
dev.app.jdbc.driver=com.mysql.jdbc.Driver
dev.app.jdbc.url=jdbc:mysql://localhost:3306/addvertisement
dev.app.jdbc.username=root
dev.app.jdbc.password=root
There is a new annotation @Value
in Spring 3.0.0M3. @Value
support not only #{...}
expressions but ${...}
placeholders as well
As mentioned @Value
does the job and it is quite flexible as you can have spring EL in it.
Here are some examples, which could be helpful:
//Build and array from comma separated parameters
//Like currency.codes.list=10,11,12,13
@Value("#{'${currency.codes.list}'.split(',')}")
private List<String> currencyTypes;
Another to get a set
from a list
//If you have a list of some objects like (List<BranchVO>)
//and the BranchVO has areaCode,cityCode,...
//You can easily make a set or areaCodes as below
@Value("#{BranchList.![areaCode]}")
private Set<String> areas;
You can also set values for primitive types.
@Value("${amount.limit}")
private int amountLimit;
You can call static methods:
@Value("#{T(foo.bar).isSecurityEnabled()}")
private boolean securityEnabled;
You can have logic
@Value("#{T(foo.bar).isSecurityEnabled() ? '${security.logo.path}' : '${default.logo.path}'}")
private String logoPath;
A possible solutions is to declare a second bean which reads from the same properties file:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
<util:properties id="appProperties" location="classpath:/WEB-INF/app.properties"/>
The bean named 'appProperties' is of type java.util.Properties and can be dependency injected using the @Resource attruibute shown above.
Another alternative is to add the appProperties bean shown below:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
<bean id="appProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true"/>
<property name="properties">
<props>
<prop key="results.max">${results.max}</prop>
</props>
</property>
</bean>
When retrieved, this bean can be cast to a java.util.Properties
which will contain a property named results.max
whose value is read from app.properties
. Again, this bean can be dependency injected (as an instance of java.util.Properties) into any class via the @Resource annotation.
Personally, I prefer this solution (to the other I proposed), as you can limit exactly which properties are exposed by appProperties, and don't need to read app.properties twice.
Easiest way in Spring 5 is to use @ConfigurationProperties
here is example
https://mkyong.com/spring-boot/spring-boot-configurationproperties-example/
A possible solutions is to declare a second bean which reads from the same properties file:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
<util:properties id="appProperties" location="classpath:/WEB-INF/app.properties"/>
The bean named 'appProperties' is of type java.util.Properties and can be dependency injected using the @Resource attruibute shown above.
Before we get Spring 3 - which allows you to inject property constants directly into your beans using annotations - I wrote a sub-class of the PropertyPlaceholderConfigurer bean that does the same thing. So, you can mark up your property setters and Spring will autowire your properties into your beans like so:
@Property(key="property.key", defaultValue="default")
public void setProperty(String property) {
this.property = property;
}
The Annotation is as follows:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface Property {
String key();
String defaultValue() default "";
}
The PropertyAnnotationAndPlaceholderConfigurer is as follows:
public class PropertyAnnotationAndPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
private static Logger log = Logger.getLogger(PropertyAnnotationAndPlaceholderConfigurer.class);
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties properties) throws BeansException {
super.processProperties(beanFactory, properties);
for (String name : beanFactory.getBeanDefinitionNames()) {
MutablePropertyValues mpv = beanFactory.getBeanDefinition(name).getPropertyValues();
Class clazz = beanFactory.getType(name);
if(log.isDebugEnabled()) log.debug("Configuring properties for bean="+name+"["+clazz+"]");
if(clazz != null) {
for (PropertyDescriptor property : BeanUtils.getPropertyDescriptors(clazz)) {
Method setter = property.getWriteMethod();
Method getter = property.getReadMethod();
Property annotation = null;
if(setter != null && setter.isAnnotationPresent(Property.class)) {
annotation = setter.getAnnotation(Property.class);
} else if(setter != null && getter != null && getter.isAnnotationPresent(Property.class)) {
annotation = getter.getAnnotation(Property.class);
}
if(annotation != null) {
String value = resolvePlaceholder(annotation.key(), properties, SYSTEM_PROPERTIES_MODE_FALLBACK);
if(StringUtils.isEmpty(value)) {
value = annotation.defaultValue();
}
if(StringUtils.isEmpty(value)) {
throw new BeanConfigurationException("No such property=["+annotation.key()+"] found in properties.");
}
if(log.isDebugEnabled()) log.debug("setting property=["+clazz.getName()+"."+property.getName()+"] value=["+annotation.key()+"="+value+"]");
mpv.addPropertyValue(property.getName(), value);
}
}
for(Field field : clazz.getDeclaredFields()) {
if(log.isDebugEnabled()) log.debug("examining field=["+clazz.getName()+"."+field.getName()+"]");
if(field.isAnnotationPresent(Property.class)) {
Property annotation = field.getAnnotation(Property.class);
PropertyDescriptor property = BeanUtils.getPropertyDescriptor(clazz, field.getName());
if(property.getWriteMethod() == null) {
throw new BeanConfigurationException("setter for property=["+clazz.getName()+"."+field.getName()+"] not available.");
}
Object value = resolvePlaceholder(annotation.key(), properties, SYSTEM_PROPERTIES_MODE_FALLBACK);
if(value == null) {
value = annotation.defaultValue();
}
if(value == null) {
throw new BeanConfigurationException("No such property=["+annotation.key()+"] found in properties.");
}
if(log.isDebugEnabled()) log.debug("setting property=["+clazz.getName()+"."+field.getName()+"] value=["+annotation.key()+"="+value+"]");
mpv.addPropertyValue(property.getName(), value);
}
}
}
}
}
}
Feel free to modify to taste
Use Spring's "PropertyPlaceholderConfigurer" class
A simple example showing property file read dynamically as bean's property
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/classes/config_properties/dev/database.properties</value>
</list>
</property>
</bean>
<bean id="devDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${dev.app.jdbc.driver}"/>
<property name="jdbcUrl" value="${dev.app.jdbc.url}"/>
<property name="user" value="${dev.app.jdbc.username}"/>
<property name="password" value="${dev.app.jdbc.password}"/>
<property name="acquireIncrement" value="3"/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="10"/>
<property name="maxStatementsPerConnection" value="11000"/>
<property name="numHelperThreads" value="8"/>
<property name="idleConnectionTestPeriod" value="300"/>
<property name="preferredTestQuery" value="SELECT 0"/>
</bean>
Property File
dev.app.jdbc.driver=com.mysql.jdbc.Driver
dev.app.jdbc.url=jdbc:mysql://localhost:3306/addvertisement
dev.app.jdbc.username=root
dev.app.jdbc.password=root
A possible solutions is to declare a second bean which reads from the same properties file:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
<util:properties id="appProperties" location="classpath:/WEB-INF/app.properties"/>
The bean named 'appProperties' is of type java.util.Properties and can be dependency injected using the @Resource attruibute shown above.
<context:property-placeholder ... />
is the XML equivalent to the PropertyPlaceholderConfigurer.
Example: applicationContext.xml
<context:property-placeholder location="classpath:test.properties"/>
Component class
private @Value("${propertyName}") String propertyField;
You also can annotate you class:
@PropertySource("classpath:/com/myProject/config/properties/database.properties")
And have a variable like this:
@Autowired
private Environment env;
Now you can access to all your properties in this way:
env.getProperty("database.connection.driver")
If you are stuck using Spring 2.5 you could define a bean for each of your properties and inject them using qualifiers. Like this:
<bean id="someFile" class="java.io.File">
<constructor-arg value="${someFile}"/>
</bean>
and
@Service
public class Thing
public Thing(@Qualifier("someFile") File someFile) {
...
Its not super readable but it gets the job done.
You also can annotate you class:
@PropertySource("classpath:/com/myProject/config/properties/database.properties")
And have a variable like this:
@Autowired
private Environment env;
Now you can access to all your properties in this way:
env.getProperty("database.connection.driver")
Source: Stackoverflow.com