Java 将spring配置映射到集成流

Java 将spring配置映射到集成流,java,spring,spring-boot,spring-integration,spring-java-config,Java,Spring,Spring Boot,Spring Integration,Spring Java Config,我有一个Spring引导/集成应用程序,其集成流从RabbitMQ队列开始。流本身和应用程序总体上运行良好,但初始入站AMQP配置有很多冗余配置 目前,我有十个数据类型s,每个数据类型的属性略有不同,其中一些需要在运行时定义。我为每个流初始化一个入站流,设置几个头,并快速将它们转储到一个公共通道中进行处理 仅一个网络诊断数据类型的Java配置如下所示: @Bean public IntegrationFlow inboundNetworkDiagnosticFlow(@Qualifier("co

我有一个Spring引导/集成应用程序,其集成流从RabbitMQ队列开始。流本身和应用程序总体上运行良好,但初始入站AMQP配置有很多冗余配置

目前,我有十个
数据类型
s,每个数据类型的属性略有不同,其中一些需要在运行时定义。我为每个流初始化一个入站流,设置几个头,并快速将它们转储到一个公共通道中进行处理

仅一个
网络诊断
数据类型
的Java配置如下所示:

@Bean
public IntegrationFlow inboundNetworkDiagnosticFlow(@Qualifier("connectionFactory") ConnectionFactory connectionFactory,
                                                    @Qualifier(BeanNames.INBOUND_EVENTS_CHANNEL) MessageChannel outbound,
                                                    @Qualifier(BeanNames.JSON_NODE_MESSAGE_CONVERTER) MessageConverter messageConverter,
                                                    @Qualifier("networkDiagnosticQueue") Queue queue,
                                                    @Value("${networkDiagnostic.numConsumers}") int numConsumers,
                                                    @Value("${networkDiagnostic.prefetchCount}") int prefetchCount) {
    return makeEventIntegrationFlow(connectionFactory, outbound, messageConverter, queue, numConsumers, prefetchCount,
            DataTypes.EVENT_NETWORK_DIAGNOSTIC);

}

@Bean
public Binding networkDiagnosticBinding(@Qualifier("networkDiagnosticQueue") Queue queue) {
    return makeFanoutBinding(queue, NETWORK_DIAGNOSTIC_EXCHANGE_NAME);
}


@Bean
public Queue networkDiagnosticQueue() {
    return makeQueue(NETWORK_DIAGNOSTIC_QUEUE_STRING);
}

@Bean
public FanoutExchange networkDiagnosticExchange() {
    return new FanoutExchange(NETWORK_DIAGNOSTIC_EXCHANGE_NAME);
}
另外九个有并行配置。我想进一步考虑这一点,以便a)消除重复,b)只需从服务器上的配置文件配置更多输入

我的总体想法是,我会有一个yaml配置文件:

data_types:
   - name: network-diagnostic
     schema: event
     window_type: hourly
     exchange_name: blahblahblah
     queue_name: blahblahblah
     ...
   - name: log-diagnostic
   ...
通过
@ConfigurationProperties
我可以将其映射到一个类,大致如下:

 /**
 * Organizes information and configuration for a DataType
 */
public class DataType {
    private String name;
    private Schema schema;
    private WindowType windowType;
    private long bucketLength;

    private String exchange;
    private String routingKey;
    ...
我需要一些方法--
RegisteralBeans
--需要所有的数据类型,这些数据类型创建所有必要的bean(及其相互关系),并对每个bean调用
SingletonBeanRegistry::registerSingleton

也就是说,我不确定该方法何时运行,以及如何运行。一方面,我需要它在配置属性创建的bean可访问之后运行,但在生命周期管理开始之前(因此我的集成流将被管理),最好在
RabbitAdmin::afterPropertiesSet
之前运行,这样我还可以获得RabbitMQ对象的隐式声明

我怎样才能做到这一点

更新:我遵照@ArtemBilan下面的建议,编写了一个模拟示例,我在这里介绍了这个示例

主要类别:

@EnableAutoConfiguration
@Configuration
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplicationBuilder parentBuilder = new SpringApplicationBuilder(DemoApplication.class);
        parentBuilder.child(ChildConfiguration.class).properties("name=bob", "message='hi how are you?'").run();
        parentBuilder.child(ChildConfiguration.class).properties("name=jane", "message='hi how are you?'").run();
    }

    @Bean
    public IntegrationFlow integrationFlow() {
        Object object = new Object();
        return IntegrationFlows.from("inputChannel")
                .handle(m -> System.out.println(object + " " + m.getPayload() + " " + System.currentTimeMillis()))
                .get();
    }
}
以下项的子配置:

@EnableAutoConfiguration
@EnableConfigurationProperties(Sample.class)
@Configuration
public class ChildConfiguration {

    @Bean
    public IntegrationFlow anotherOutgoingFlow(Sample sample) {
        return IntegrationFlows
                .from(() -> new GenericMessage<>("hello " + sample.getName() + "; " + sample.getMessage()),
                        m -> m.poller(Pollers.fixedDelay(500)))
                .channel("inputChannel")
                .get();
    }
}
打印,例如:

2016-03-25 17:12:04.109  INFO 24637 --- [           main] com.example.DemoApplication              : Started DemoApplication in 0.169 seconds (JVM running for 3.878)
java.lang.Object@25c4da11 hello bob; 'hi how are you?' 1458940324438
java.lang.Object@25c4da11 hello jane; 'hi how are you?' 1458940324607
java.lang.Object@25c4da11 hello bob; 'hi how are you?' 1458940324938
java.lang.Object@25c4da11 hello jane; 'hi how are you?' 1458940325108
java.lang.Object@25c4da11 hello bob; 'hi how are you?' 1458940325439

当您能够基于提供的环境重用模板配置时,请考虑为您的应用程序使用父/子体系结构


有关更多信息,请参阅。

对不起,您能再解释一下吗?如果我理解你的意思,我会有一个main作为父级传递顶级配置,并为每个
数据类型
创建一个子上下文——这很有意义——但我不清楚当时如何引用
ConfigurationProperties
定义的对象——这些对象不是在已经存在应用程序上下文后定义的吗?m-m-m。不,如果您在子应用程序上下文源中的适当位置使用
@EnableConfigurationProperties(DataType.class)
。也许我有误解,但您似乎在建议一种基于环境交换bean定义的方法——将一组数据类型交换为另一组数据类型——但我的问题是如何在运行时基于config.OK在单个环境中定义多个聚合集成流。也许我们彼此不了解。所以,我很高兴听到其他人对这件事的看法。对我来说,在一些
@Configuration
类上,这看起来像genric
@EnableConfigurationProperties(DataType.class)
,您将其用作子上下文的资源,并在解析来自顶层
应用程序.yml的集合的数据类型后,基于具体的
数据类型为其提供特定的
环境。我要试一试——谢谢你,阿泰姆。
2016-03-25 17:12:04.109  INFO 24637 --- [           main] com.example.DemoApplication              : Started DemoApplication in 0.169 seconds (JVM running for 3.878)
java.lang.Object@25c4da11 hello bob; 'hi how are you?' 1458940324438
java.lang.Object@25c4da11 hello jane; 'hi how are you?' 1458940324607
java.lang.Object@25c4da11 hello bob; 'hi how are you?' 1458940324938
java.lang.Object@25c4da11 hello jane; 'hi how are you?' 1458940325108
java.lang.Object@25c4da11 hello bob; 'hi how are you?' 1458940325439