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

前端 未结 8 685
醉梦人生
醉梦人生 2020-11-27 14:25

What I would like to achieve is the ability to "dynamically" (i.e. based on a property defined in a configuration file) enable/disable the importing of a child Spr

相关标签:
8条回答
  • 2020-11-27 14:52

    Another option is to have your app load a modules-config.xml file that is located in the /conf folder and edit it during the install/config phase to uncomment the modules you want loaded.

    This is the solution I'm using with a web application that serves as a container for different integration modules. The web application is distributed with all the different integration modules. A modules-config.xml is placed in tomcat's /conf folder and the conf folder is added to the classpath (via catalina.properties/common.loader property). My web app webapp-config.xml has a <import resource="classpath:/modules-config.xml"/> to get it loaded.

    0 讨论(0)
  • 2020-11-27 14:58

    You can override contextInitialized(javax.servlet.ServletContextEvent event) in your own ContextLoaderListener and set required System property before super.contextInitialized(event) called like this

    package com.mypackage;
    import org.springframework.web.context.ContextLoaderListener;
    public class MyContextLoaderListener extends ContextLoaderListener {
        public void contextInitialized(javax.servlet.ServletContextEvent event) {
            System.setProperty("xyz", "import-file-name.xml");
            super.contextInitialized(event);
        }
    }
    

    And than replace ContextLoaderListener to MyContextLoaderListener in your web.xml

    <listener>
        <listener-class>com.mypackage.MyContextLoaderListener</listener-class>
    </listener>
    

    Now you can use in your spring.xml

    <import resource="${xyz}" /> 
    

    I hope this will help.

    0 讨论(0)
  • 2020-11-27 14:59

    Another one to consider for Spring 3.0:

     <alias name="Whatever" alias=""Whatever-${yyzzy}" />
    

    where ${xyzzy} interpolates a property from the system properties.

    0 讨论(0)
  • 2020-11-27 15:04

    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

    0 讨论(0)
  • 2020-11-27 15:04

    With Spring 3.1.x you can use bean profiles to achieve conditional resource import and bean instantiation. This is of course of no help if you are using an earlier version :)

    0 讨论(0)
  • 2020-11-27 15:05

    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

    0 讨论(0)
提交回复
热议问题