I have a Standalone Application, this application calculates a value (Property) and then starts a Spring Context.
My question is how can I add that calculated property to the spring context, so that I can use it like properties loaded from a property file (@Value("${myCalculatedProperty}"))?
To illustrate it a bit
public static void main(final String[] args) {
String myCalculatedProperty = magicFunction();
AbstractApplicationContext appContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
//How to add myCalculatedProperty to appContext (before starting the context)
appContext.getBean(Process.class).start();
}
ApplicationContext.xml:
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:*.properties" />
</bean>
<context:component-scan base-package="com.example.app"/>
It is a Spring 3.0 Application.
You will need to add the application. properties file in your classpath. If you are using Maven or Gradle, you can just put the file under src/main/resources . If you are not using Maven or any other build tools, put that under your src folder and you should be fine.
In Spring 3.1 you can implement your own PropertySource, see: Spring 3.1 M1: Unified Property Management.
First, create your own PropertySource implementation:
private static class CustomPropertySource extends PropertySource<String> {
public CustomPropertySource() {super("custom");}
@Override
public String getProperty(String name) {
if (name.equals("myCalculatedProperty")) {
return magicFunction(); //you might cache it at will
}
return null;
}
}
Now add this PropertySource before refreshing the application context:
AbstractApplicationContext appContext =
new ClassPathXmlApplicationContext(
new String[] {"applicationContext.xml"}, false
);
appContext.getEnvironment().getPropertySources().addLast(
new CustomPropertySource()
);
appContext.refresh();
From now on you can reference your new property in Spring:
<context:property-placeholder/>
<bean class="com.example.Process">
<constructor-arg value="${myCalculatedProperty}"/>
</bean>
Also works with annotations (remember to add <context:annotation-config/>):
@Value("${myCalculatedProperty}")
private String magic;
@PostConstruct
public void init() {
System.out.println("Magic: " + magic);
}
You can add the calculated value to the system properties:
System.setProperty("placeHolderName", myCalculatedProperty);
If You are controlling the creation of ApplicationContext as in Your example than You can always add a BeanRegistryPostProcessor to add a second PropertyPlaceholderConfigurer into the context. It should have ignoreUnresolvablePlaceholders="true" and order="1" and resolve only the custom calculated properties using the Properties object. All other properties should be resolved by the PropertyPlaceholderConfigurer from the XML that should have order="2".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With