spring-boot - 为什么 Spring Boot Application 在添加 spring-cloud-bus 依赖项后记录它启动了两次

标签 spring-boot rabbitmq spring-amqp spring-rabbit spring-cloud-bus

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

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

还有一个ApplicationListener类来监听ApplicationEvent:

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')
}

现在,当我运行这个 Spring Boot 应用程序时,我看到这个日志打印了两次:

[main] c.m.S.SpringBootHelloWorldApplication : Started SpringBootHelloWorldApplication in ... seconds (JVM running for ...)

通常,此日志只打印一次,但如果我添加这些依赖项,它会打印两次:

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 发生了两次。

为什么会这样? 有什么办法可以避免吗?

最佳答案

spring-cloud-bus 使用 spring-cloud-stream 将绑定(bind)器放在单独的引导子应用程序上下文中。

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

@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("-------------------------------------");
        }
    }

}

关于spring-boot - 为什么 Spring Boot Application 在添加 spring-cloud-bus 依赖项后记录它启动了两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47344882/

相关文章:

Spring AMQP 恢复器无法与 SimpleMessageListenerContainer 一起使用

java - Spring AMQP 处理已删除的队列

java - Spring Security 401 未经授权,即使有 permitAll

spring - FlywayAutoConfiguration 没有 "see"数据源

java - 在 RabbitMQ BasicPublish 期间避免数据复制

sql-server - RabbitMQ、ZeroMQ、Service Broker 或类似的解决方案是否适合创建高可用性数据库 Web 服务?

java - 消息传递的幂等屏障

java - 如何添加一个额外的监听器来监听 Spring AMQP 队列?

java - 如何根据属性文件中的设置强制服务使用特定存储库?

spring - Prometheus UI,Spring Boot 应用程序的 Grafana 设置