Reputation: 120761
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.
Upvotes: 20
Views: 55898
Reputation: 6801
If you are controlling the creation of ApplicationContext
as in your example, 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"
.
Upvotes: 3
Reputation: 340708
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);
}
Upvotes: 30
Reputation: 21564
Your myCalculatedProperty
must be contained within one of your properties file (which are injected by the Spring propertyPlaceholderConfigurer
).
EDIT : simply use the setter, something like this
public static void main(final String[] args) {
String myCalculatedProperty = magicFunction();
AbstractApplicationContext appContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
Process p = appContext.getBean(Process.class);
p.setMyCalculatedProperty(myCalculatedProperty);
p.start();
}
Upvotes: 0
Reputation: 2068
You can add the calculated value to the system properties:
System.setProperty("placeHolderName", myCalculatedProperty);
Upvotes: 8