Spring boot 为什么Spring启动应用程序记录在添加Spring云总线依赖项后启动了两次

Spring boot 为什么Spring启动应用程序记录在添加Spring云总线依赖项后启动了两次,spring-boot,rabbitmq,spring-amqp,spring-rabbit,spring-cloud-bus,Spring Boot,Rabbitmq,Spring Amqp,Spring Rabbit,Spring Cloud Bus,这是我的Spring boot应用程序中的简单代码: package com.maxxton.SpringBootHelloWorld; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootHelloWorldApp

这是我的Spring boot应用程序中的简单代码:

package com.maxxton.SpringBootHelloWorld;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootHelloWorldApplication {

  public static void main(String[] args) {
    SpringApplication.run(SpringBootHelloWorldApplication.class, args);
  }
}
以及用于侦听ApplicationEvent的ApplicationListener类:

package com.maxxton.SpringBootHelloWorld;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class Test implements ApplicationListener {

  @Override
  public void onApplicationEvent(ApplicationEvent event) {
    if (event.getClass().getSimpleName().equals("ApplicationReadyEvent")) {
      System.out.println("-------------------------------------");
      System.out.println(event.getClass().getSimpleName());
      System.out.println("-------------------------------------");
    }
  }
}
build.gradle包含以下依赖项:

dependencies {

    compile("org.springframework.boot:spring-boot-starter-amqp")
    compile("org.springframework.cloud:spring-cloud-starter-bus-amqp")

    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.springframework.boot:spring-boot-starter')
    compile("org.springframework.cloud:spring-cloud-starter")
    compile("org.springframework.cloud:spring-cloud-starter-security")
    compile("org.springframework.cloud:spring-cloud-starter-eureka")
    testCompile('org.springframework.boot:spring-boot-starter-test')
}
compile("org.springframework.boot:spring-boot-starter-amqp")
compile("org.springframework.cloud:spring-cloud-starter-bus-amqp")
现在,当我运行这个spring boot应用程序时,我看到这个日志打印了两次:

[main] c.m.S.SpringBootHelloWorldApplication : Started SpringBootHelloWorldApplication in ... seconds (JVM running for ...)
通常,此日志只打印一次,但如果添加以下依赖项,则会打印两次:

dependencies {

    compile("org.springframework.boot:spring-boot-starter-amqp")
    compile("org.springframework.cloud:spring-cloud-starter-bus-amqp")

    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.springframework.boot:spring-boot-starter')
    compile("org.springframework.cloud:spring-cloud-starter")
    compile("org.springframework.cloud:spring-cloud-starter-security")
    compile("org.springframework.cloud:spring-cloud-starter-eureka")
    testCompile('org.springframework.boot:spring-boot-starter-test')
}
compile("org.springframework.boot:spring-boot-starter-amqp")
compile("org.springframework.cloud:spring-cloud-starter-bus-amqp")
这是完整的日志:

2017-11-17 15:44:07.372  INFO 5976 --- [           main] o.s.c.support.GenericApplicationContext  : Refreshing org.springframework.context.support.GenericApplicationContext@31c7c281: startup date [Fri Nov 17 15:44:07 IST 2017]; root of context hierarchy
-------------------------------------
ApplicationReadyEvent
-------------------------------------
2017-11-17 15:44:07.403  INFO 5976 --- [           main] c.m.S.SpringBootHelloWorldApplication    : Started SpringBootHelloWorldApplication in 1.19 seconds (JVM running for 10.231)
2017-11-17 15:44:09.483  WARN 5976 --- [           main] o.s.amqp.rabbit.core.RabbitAdmin         : Failed to declare exchange: Exchange [name=springCloudBus, type=topic, durable=true, autoDelete=false, internal=false, arguments={}], continuing... org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect
2017-11-17 15:44:09.492  INFO 5976 --- [           main] o.s.integration.channel.DirectChannel    : Channel 'a-bootiful-client.springCloudBusOutput' has 1 subscriber(s).
2017-11-17 15:44:09.493  INFO 5976 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 0
2017-11-17 15:44:09.530  INFO 5976 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
2017-11-17 15:44:09.530  INFO 5976 --- [           main] o.s.i.channel.PublishSubscribeChannel    : Channel 'a-bootiful-client.errorChannel' has 1 subscriber(s).
2017-11-17 15:44:09.530  INFO 5976 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : started _org.springframework.integration.errorLogger
2017-11-17 15:44:09.530  INFO 5976 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147482647
2017-11-17 15:44:09.539  INFO 5976 --- [           main] c.s.b.r.p.RabbitExchangeQueueProvisioner : declaring queue for inbound: springCloudBus.anonymous.kZ1vvxHaRfChKe1TncH-MQ, bound to: springCloudBus
2017-11-17 15:44:11.562  WARN 5976 --- [           main] o.s.amqp.rabbit.core.RabbitAdmin         : Failed to declare exchange: Exchange [name=springCloudBus, type=topic, durable=true, autoDelete=false, internal=false, arguments={}], continuing... org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect
2017-11-17 15:44:13.587  WARN 5976 --- [           main] o.s.amqp.rabbit.core.RabbitAdmin         : Failed to declare queue: Queue [name=springCloudBus.anonymous.kZ1vvxHaRfChKe1TncH-MQ, durable=false, autoDelete=true, exclusive=true, arguments={}], continuing... org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect
2017-11-17 15:44:15.611  WARN 5976 --- [           main] o.s.amqp.rabbit.core.RabbitAdmin         : Failed to declare binding: Binding [destination=springCloudBus.anonymous.kZ1vvxHaRfChKe1TncH-MQ, exchange=springCloudBus, routingKey=#], continuing... org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect
2017-11-17 15:44:17.662  INFO 5976 --- [           main] o.s.i.a.i.AmqpInboundChannelAdapter      : started inbound.springCloudBus.anonymous.kZ1vvxHaRfChKe1TncH-MQ
2017-11-17 15:44:17.662  INFO 5976 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : Adding {message-handler:inbound.springCloudBus.default} as a subscriber to the 'bridge.springCloudBus' channel
2017-11-17 15:44:17.662  INFO 5976 --- [           main] o.s.i.endpoint.EventDrivenConsumer       : started inbound.springCloudBus.default
2017-11-17 15:44:17.663  INFO 5976 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147483647
2017-11-17 15:44:17.714  INFO 5976 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
-------------------------------------
ApplicationReadyEvent
-------------------------------------
2017-11-17 15:44:17.717  INFO 5976 --- [           main] c.m.S.SpringBootHelloWorldApplication    : Started SpringBootHelloWorldApplication in 20.131 seconds (JVM running for 20.545)
如您所见,ApplicationReadyEvent发生了两次

为什么会这样?
有什么方法可以避免这种情况吗?

您的应用程序.yml/.xml中是否使用多绑定rabbitmq配置

如果是肯定的,那么您可以尝试排除RabbitAutoConfiguration

@EnableDiscoveryClient
@EnableAutoConfiguration(exclude = {RabbitAutoConfiguration.class})
@SpringBootApplication
public class SpringBootHelloWorldApplication {

  public static void main(String[] args) {
    SpringApplication.run(SpringBootHelloWorldApplication.class, args);
  }
}

SpringCloudBus使用SpringCloudStream,它将绑定器放在单独的启动子应用程序上下文中

您应该让事件侦听器知道它正在运行的应用程序上下文。您还可以使用泛型来选择您感兴趣的事件类型

@Component
public class Test implements ApplicationListener<ApplicationReadyEvent>, 
                             ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        if (event.getApplicationContext().equals(this.applicationContext)) {
            System.out.println("-------------------------------------");
            System.out.println(event.getClass().getSimpleName());
            System.out.println("-------------------------------------");
        }
    }

}
@组件
公共类测试实现ApplicationListener,
ApplicationContextAware{
私有应用程序上下文应用程序上下文;
@凌驾
public void setApplicationContext(ApplicationContext ApplicationContext)抛出BeansException{
this.applicationContext=applicationContext;
}
@凌驾
ApplicationEvent上的公共无效(ApplicationReadyEvent事件){
if(event.getApplicationContext().equals(this.applicationContext)){
System.out.println(“-----------------------------------------”;
System.out.println(event.getClass().getSimpleName());
System.out.println(“-----------------------------------------”;
}
}
}

不,我没有使用多个绑定。从未使用过Spring Cloud Bus,但看起来可能是它导致了这种情况。根据,您可以启用跟踪,以便查看并检查是否存在错误。一个疯狂的想法可能是,应用程序正在侦听自己的状态更改,因此消耗自己的事件并复制输出…因此,您是说,@gary russell如果我们使用spring云总线依赖项,“Started SpringBootHelloWorldApplication in…”将被记录两次,因为spring cloud bus使用spring cloud stream,它将绑定器放在一个单独的启动子系统中。只有在您不接受我的建议并让您的侦听器知道它声明为int的应用程序上下文时,才会记录两次。我已根据您的建议进行了更改,现在侦听器感知只打印了一次,但是“已在中启动SpringBootHelloWorldApplication…”仍记录了两次。