【问题标题】:SpringBoot CommandLineRunner run() method not being calledSpringBoot CommandLineRunner run() 方法未被调用
【发布时间】:2018-06-20 12:30:35
【问题描述】:

我正在学习 SpringBoot。我的(微不足道的)问题是我无法从 SpringBoot 调用的 CommandLineRunner 接口中获取 run() 方法。 我正在使用 Java 8、Eclipse Oxygen、Maven,并且我正在将我的项目作为“Spring Boot App”运行。 代码是:

package com.clarivate.dataviewer;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DvMain implements CommandLineRunner{

static Logger logger = LogManager.getRootLogger();

public static void main(String[] args) {
    logger.debug("DS1A in main()");
    //SpringApplication.run(DvMain.class, args);
    SpringApplication app = new SpringApplication(DvMain.class);
    //ConfigurableApplicationContext app = SpringApplication.run(DvMain.class, args);
    logger.debug("DS1B in main()");
    app.run(args);
}

@Override
public void run(String... args) throws Exception {
    // This does not get called
    logger.debug("DS4 this line is never printed");
}
}

覆盖的 run() 方法不会被调用。 我尝试创建一个单独的类来实现 CommandLineRunner 但同样的问题。控制台跟踪是:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/Users/44/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/Users/44/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.10.0/log4j-slf4j-impl-2.10.0.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
12:58:42.225 [main] DEBUG  - DS1A in main()
12:58:42.289 [main] DEBUG  - DS1B in main()

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.2.RELEASE)

2018-06-20 12:58:42.614  INFO 16924 --- [           main] com.clarivate.dataviewer.DvMain          : Starting DvMain on 44-TPD-A with PID 16924 (C:\workspace_oxyegen\dataviewer\target\classes started by 44 in C:\workspace_oxyegen\dataviewer)
2018-06-20 12:58:42.615  INFO 16924 --- [           main] com.clarivate.dataviewer.DvMain          : No active profile set, falling back to default profiles: default
2018-06-20 12:58:42.655  INFO 16924 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6b4a4e18: startup date [Wed Jun 20 12:58:42 BST 2018]; root of context hierarchy
2018-06-20 12:58:43.266  INFO 16924 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-06-20 12:58:43.279  INFO 16924 --- [           main] com.clarivate.dataviewer.DvMain          : Started DvMain in 0.988 seconds (JVM running for 1.684)
2018-06-20 12:58:43.294  INFO 16924 --- [       Thread-2] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6b4a4e18: startup date [Wed Jun 20 12:58:42 BST 2018]; root of context hierarchy
2018-06-20 12:58:43.296  INFO 16924 --- [       Thread-2] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown

我确定我犯了一个简单的错误,但我就是看不到它。任何帮助表示赞赏。

【问题讨论】:

  • 你能解决这个问题吗?

标签: java spring-boot


【解决方案1】:

首先,调用来自您的 run 方法。但不记录任何内容,因为您的记录器存在一些问题。您可以使用System.out.println(...) 来确认这一点。

  1. 如下更改您的 Logger 声明。

    private static final Logger logger = LoggerFactory.getLogger(DvMain.class);
    
  2. 您没有使用正确的库。使用来自 slf4j 而不是 log4j

    的 Logger
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    

【讨论】:

  • 两种 log4j 方法都有效。如果我将 logging.level.root=DEBUG 添加到 application.properties 中,则会打印 DS4 行。看起来日志级别是在引导阶段设置的,这是有道理的,但是 DS1 行和 DS4 行的级别不同。无论如何,不​​管是什么原因,谢谢指点
  • Springboot 不适用于 log4j。你可以搜索这方面的文章。只需输入谷歌。 :) 干杯。
  • 我认为你是对的。如果我设置 logging.level.root=DEBUG 然后我会在控制台上打印出大量垃圾信息,如果我没有设置日志记录级别,我不会得到这些信息。那么默认的日志记录级别是什么?谁知道呢。
  • 所以默认级别是info,但是可以在spring boot阶段之前打印一些debug信息,就是为了迷惑大家,nice。
【解决方案2】:

logging.level.root=debug 添加到您的 application.properties 文件中。

默认情况下,Spring Boot 不显示调试级别日志记录。显示第一条调试消息是因为它们在您的 Spring 应用程序启动之前被调用。

【讨论】:

    【解决方案3】:

    那是因为你的 DvMain 类本身没有注释为 Spring 上下文 @Component,所以 spring 找不到你的 pojo 来执行你覆盖的 run 方法。

    要解决,只需将@Component 添加到类中,您将在日志中看到跟踪。

    【讨论】:

    • @SpringBootApplication@SpringBootConfiguration组成,@Configuration又由@Component组成,所以DvMain实际上是一个Spring组件。
    • 这应该是选择的答案。