How to achieve conditional resource import in a Spring XML context? How to achieve conditional resource import in a Spring XML context? xml xml

How to achieve conditional resource import in a Spring XML context?


Prior to Spring 4, the closest you can get using standard Spring components is:

<import resource="Whatever-${yyzzy}.xml"/>

where ${xyzzy} interpolates a property from the system properties. (I use a hacky custom version of the context loader class that adds properties from other places to the system properties object before starting the loading process.)

But you can also get away with importing lots of unnecessary stuff ... and use various tricks to only cause the necessary beans to be instantiated. These tricks include:

  • placeholder and property substitution
  • selecting different beans using the new Spring expression language,
  • bean aliases with placeholders in the target name,
  • lazy bean initialization, and
  • smart bean factories.


This is now completely possible, using Spring 4.

In your main application content file

<bean class="com.example.MyConditionalConfiguration"/>

And the MyConditionalConfiguration looks like

@Configuration@Conditional(MyConditionalConfiguration.Condition.class)@ImportResource("/com/example/context-fragment.xml")public class MyConditionalConfiguration {    static class Condition implements ConfigurationCondition {         @Override         public ConfigurationPhase getConfigurationPhase() {             return ConfigurationPhase.PARSE_CONFIGURATION;         }         @Override         public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {             // only load context-fragment.xml if the system property is defined             return System.getProperty("com.example.context-fragment") != null;         }    }}

And then finally, you put the bean definitions you want included in the /com/example/context-fragment.xml

See the JavaDoc for @Conditional


As mentioned earlier, this can be easily accomplished with profiles if you're using Spring 3.1+

<!-- default configuration - will be loaded if no profile is specified --><!-- This will only work if it's put at the end of the configuration file --><!-- so no bean definitions after that --><beans profile="default">    <import resource="classpath:default.xml" /></beans><!-- some other profile --><beans profile="otherProfile">    <import resource="classpath:other-profile.xml" /></beans>

otherProfile can be easily activated with e.g.

mvn install -Dspring.profiles.active=otherProfile

if you're using different profiles in tests, just add -DforkMode=never to make sure that the tests will run inside same VM, therefore the param spring.profiles.active wont be lost