如何在Spring XML上下文中实现条件资源导入?

2022-08-31 15:33:50

我想实现的是“动态”(即基于配置文件中定义的属性)启用/禁用子Spring XML上下文导入的能力。

我想象这样的事情:

<import condition="some.property.name" resource="some-context.xml"/>

如果属性被解析(解析为布尔值),当为 true 时,将导入上下文,否则则不导入上下文。

到目前为止,我的一些研究:

  • 编写自定义命名空间处理程序(和相关类),以便我可以在自己的命名空间中注册自己的自定义元素。例如:<myns:import condition="some.property.name" resource="some-context.xml"/>

    这种方法的问题在于,我不想从Spring复制整个资源导入逻辑,而且对我来说,我需要委派什么来执行此操作并不明显。

  • 重写以扩展“import”元素解析和解释的行为(在方法中发生)。但是,我不确定在哪里可以注册此扩展名。DefaultBeanDefinitionDocumentReaderimportBeanDefinitionResource


答案 1

在 Spring 4 之前,使用标准 Spring 组件可以获得的最接近的组件是:

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

其中,从系统属性中插入属性。(我使用上下文加载程序类的黑客自定义版本,该类在开始加载过程之前将其他地方的属性添加到系统属性对象。${xyzzy}

但是您也可以通过导入大量不必要的东西来逃脱...并使用各种技巧来仅使必要的bean被实例化。这些技巧包括:

  • 占位符和属性替换
  • 使用新的Spring表达式语言选择不同的豆子,
  • 目标名称中带有占位符的 Bean 别名,
  • 懒豆初始化,以及
  • 智能豆工厂。

答案 2

现在,使用Spring 4,这是完全可能的。

在主应用程序内容文件中

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

而 MyConditionalConfiguration 看起来像

@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;
         }
    }
}

最后,您将要包含的bean定义放在/com/example/context-fragment中.xml

有关@Conditional,请参阅 JavaDoc


推荐