Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
218 views
in Technique[技术] by (71.8m points)

java - Load properties file in Spring depending on profile

I have a Spring 3.1 application. Let's say it has an XML with the following content:

<context:property-placeholder location="classpath:somename.properties" />

<context:property-placeholder location="classpath:xxx.properties" />

I would like some.properties to be always loaded (let's assume it exists), but the xxx part of the second place holder to be replaced by some name depending on the active profile. I've tried with this:

<beans profile="xx1">
    <context:property-placeholder location="classpath:xx1.properties" />
</beans>

<beans profile="xx2">
    <context:property-placeholder location="classpath:xx2.properties" />
</beans>

Also, both files have properties with the same key but different value.

But it didn't work as some later bean that has a placeholder for one property whose key is defined in xx1.properties (and xx2.properties) makes Spring complain that the key is not found in the application context.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can do:

  <context:property-placeholder location="classpath:${spring.profiles.active}.properties" />

It works fine, but is perhaps not adapted when using multiple profiles in the same time.


When declaring 2 property placeholders, if the 1st one does not contain all the applications keys, you should put the attribute ignoring unresolvable = true, so that the 2nd placeholder can be used. I'm not sure if it is what you want to do, it may if you want both xx1 and xx2 profiles be active in the same time.

Note that declaring 2 propertyplaceholders like that make them independant, and in the declaration of xx2.properties, you can't reuse the values of xx1.properties.


If you need something more advanced, you can register your PropertySources on application startup.

web.xml

  <context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>com.xxx.core.spring.properties.PropertySourcesApplicationContextInitializer</param-value>
  </context-param>

file you create:

public class PropertySourcesApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

  private static final Logger LOGGER = LoggerFactory.getLogger(PropertySourcesApplicationContextInitializer.class);

  @Override
  public void initialize(ConfigurableApplicationContext applicationContext) {
    LOGGER.info("Adding some additional property sources");
    String profile = System.getProperty("spring.profiles.active");
    // ... Add property sources according to selected spring profile 
    // (note there already are some property sources registered, system properties etc)
    applicationContext.getEnvironment().getPropertySources().addLast(myPropertySource);
  }

}

Once you've done it you just need to add in your context:

<context:property-placeholder/>

Imho it's the best way to deal with spring properties, because you do not declare local properties everywhere anymore, you have a programmatic control of what is happening, and property source xx1 values can be used in xx2.properties.


At work we are using it and it works nicely. We register 3 additional property sources: - Infrastructure: provided by Puppet - Profile: a different property loaded according to the profile. - Common: contains values as default, when all profiles share the same value etc...


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...