I currently work on a web application based on Spring 3.1.0.M1, annotations based, and I have a problem with resolving property placeholders in one specific place of my appl
Since Spring 3.0.3 there is EmbeddedValueResolverAware which will work same way as mentioned by another post which uses appContext.getBeanFactory().resolveEmbeddedValue("${prop}")
call.
To solve the problem:
Make your class to implement EmbeddedValueResolverAware interface and you will get resolver injected for you
Then where you will be able to retrieve properties as demonstrated in a code snippet:
String propertyValue = resolver.resolveStringValue("${your.property.name}");
Then your bean does not need to depend on ApplicationContext to retrieve properties you need.
There is one more possible solution: make tag classes @Configurable via AspectJ and enable either compile-time or load-time weaving. Then, I could use usual Spring @Value annotations in my custom tags. But, really, I don't want to set up weaving infrastructure just because of a couple of classes. Still searching for a way to resolve placeholder via ApplicationContext.
I think rather than focusing on inner working of context place holder, you can simply define a new util:properties like this:
<util:properties id="appProperties" location="classpath:app.properties" />
and in your code, use it like this:
Properties props = appContext.getBean("appProperties", Properties.class);
OR like this wherever you can do DI:
@Value("#{appProperties['app.resources.path']}")
One option is to add a PropertySource
(here MapPropertySource
to exemplify an in-memory configuration) to a ConfigurableEnvironment
and ask it to resolve properties for you.
public class Foo {
@Autowired
private ConfigurableEnvironment env;
@PostConstruct
public void setup() {
env.getPropertySources()
.addFirst(new MapPropertySource("my-propertysource",
ImmutableMap.<String, Object>of("your.property.name", "the value")));
env.resolvePlaceholders("your.property.name");
}
}
Optionally annotate the Foo
class with @Configuration
to enjoy the power of programmatic configuration in favor of XML
.
Since version 3.0, Spring keeps a list of String resolver in the beanFactory. You can use it like this:
String value = appContext.getBeanFactory().resolveEmbeddedValue("${prop}");
The javadoc states this method as for resolving embedded values such as annotation attributes so maybe we are circumventing its usage, but it works.
Just to add a complete answer, I'm adding this.
You can do it with a custom class like this.
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.util.StringValueResolver;
import org.springframework.lang.Nullable;
public class MyValueResolver implements EmbeddedValueResolverAware {
@Nullable
private StringValueResolver embeddedValueResolver;
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.embeddedValueResolver = resolver;
}
public String readMyProperty(String propertyString){
return embeddedValueResolver.resolveStringValue(propertyString);
}
}
This propertyString
should be passed as "${my.property}"
.
Given that in .properties
file it is presented as
my.property=myPropertyValue