How to achieve conditional resource import in a Spring XML context?
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
Importing resource conditionally in spring application context
Use Spring profiles.
<beans profile="not_test">
<import resource="classpath:context/caching-context.xml" />
</beans>
More information in Spring documentation and on the blog post.
Spring Import resource based on property in properties file - without using spring profile - Conditional Context Loading
You can use Spring 4's Conditionals to achieve that behaviour
For instance:
@Configuration
@Conditional(MyConditionalProd.class)
@ImportResource("classpath*:prod-config.xml")
public class MyConditionalProdConfig {}
MyConditionalProd would implement the conditional logic:
public class MyConditionalProd implements ConfigurationCondition{
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.PARSE_CONFIGURATION;
}
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String property = context.getEnvironment().getProperty("someProperty");
if("prod".equals(property)) {
return true;
}else{
return false;
}
}
}
Conditionally import xml resource in Spring integration
Consider to use Spring Profiles
With that you should do something like this:
Where that <import>
will be included only if http.flow
profile is active.
Spring 3.1 PropertySourcesPlaceholderConfigurer and conditional import
Footnote [2] of your link:
[2]: Because processing of <import/>
elements necessarily occurs before BeanFactoryPostProcessors are invoked, meaning that even PropertyPlaceholderConfigurer could not help here. Because the Environment and its set of PropertySources are configured before container refresh, placeholders in elements can be resolved against the Environment without any lifecycle issues.
UPDATE:
According to the javadoc for PropertySourcesPlaceholderConfigurer, PropertySourcesPlaceholderConfigurer
is a BeanFactoryPostProcessor
, so what the footnote really says is that the import is resolved before the PropertySourcesPlaceholderConfigurer is installed, so it will not work either (in fact, at the time the <import/>
is resolved, the configurer might not even exist yet!) Yes, when it is installed it will look at the Environment
, but you cannot use it to resolve inside an <import/>
, because at that time no postprocessors are operative. And that includes PropertySourcesPlaceholderConfigurer
.
Basically Spring XML context setup goes more or less like this:
- Context is created.
Environment
is set.- XML is read (all XML, resolving imports if necessary). Bean definitions are created.
BeanFactoryPostProcessor
s are installed and invoked, processing bean definitions.BeanPostProcessor
s are installed.- Beans are instantiated according to the bean definitions. BeanPostProcessors are applied.
This is a similar problem as that which causes that you cannot use the order
property of many postprocessors to apply a BeanPostProccesor
before a BeanFactoryPostProcessor
(to do something like make a PropertyPlaceholderConfigurer
resolve placeholders from a @PersistenceContext
): the behaviour is hardcoded in the Spring application context, so you have to work around it by specializing some Spring classes.
Does resource import order matters in Spring XML?
Yes, order matters. If you declare a bean in one imported file and then declare a bean with the same name in a subsequently imported file, the first bean declaration is overridden.
UPDATE: To more directly address your question, it is fine to have beans in earlier imports refer to beans in later imports. Order does not matter in this way.
Related Topics
Tomcat - Maxthreads VS Maxconnections
In Java 8, Why Is the Default Capacity of Arraylist Now Zero
Java Error: Cannot Make a Static Reference to the Non-Static Method
How Does the Jvm Ensure That System.Identityhashcode() Will Never Change
Write a Program That Will Surely Go into Deadlock
How to Convert Iterable to Collection
"Noclassdeffounderror: Could Not Initialize Class" Error
What's the Difference Between a Resource, Uri, Url, Path and File in Java
Sharing a Persistence Unit Across Components in a .Ear File
How to Get Java Logging Output to Appear on a Single Line
Java:Does Wait() Release Lock from Synchronized Block
How to Serialize Only the Id of a Child with Jackson
Comparing Boxed Long Values 127 and 128