没有通过 SLF4J 将 Guice 注入问题归档

Not getting Guice injection issues via SLF4J to file

我是在做错什么,还是这真的是预期的行为?让我解释一下:

当尝试使用 Guice DI 运行 Java 程序时,如果我的类路径有问题(或任何其他绑定问题),我希望得到一个看起来像这样的异常:

Exception in thread "main" com.google.inject.CreationException: Guice creation errors:

1) Error injecting constructor, java.lang.NoClassDefFoundError: Could not initialize class <any class here>

这实际上让我知道我有一个类路径问题,这是我喜欢 Guice 的地方之一(告诉你到底出了什么问题)。

当我 运行 通过命令行使用 SLF4J(特别是 logback 实现)这个程序时,我能够得到那个错误,但只在控制台输出中。如果我 运行 以一种将所有控制台输出转移到 /dev/null 的方式(例如),异常永远不会进入文件,所以我不能告诉它正在发生。我可以在错误发生之前尽可能多地记录日志,所以在这方面这不是配置错误的问题。我什至尝试将 jcl-over-slf4j 和 log4j-over-slf4j jar 添加到类路径中以尝试获取一些无济于事的东西。

也许我没有使用正确的关键字,但我找不到其他人报告相同的问题,所以我无法判断这是我的配置问题还是 "feature"吉斯

基本上,这是配置问题还是 Guice 中的 "feature"/错误,我无法在日志文件中看到绑定异常?

对于任何仍然感兴趣的人,这里是我的 logback.xml:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>debug.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <FileNamePattern>debug.%i.log.zip</FileNamePattern>
            <MinIndex>1</MinIndex>
            <MaxIndex>10</MaxIndex>
        </rollingPolicy>

        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>2MB</MaxFileSize>
        </triggeringPolicy>
    </appender>

    <appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="FILE" />
    </appender>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
            </pattern>
        </encoder>
    </appender>

    <appender name="ASYNC_CONSOLE" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="STDOUT" />
    </appender>

    <root level="debug">
        <appender-ref ref="ASYNC_FILE" />
        <appender-ref ref="ASYNC_CONSOLE" />
    </root>
</configuration>

我读到 Guice 使用 Java 记录器来实现它。我相信您看到的是 Guice 使用一个记录器(记录到控制台),然后使用您想要的日志记录配置配置 SLF4J。您是否将 Guice 设置为使用 SLF4J 实现其记录器?

您看到的不是日志警告,它是主线程上的异常,并且 Java 在终止您的程序之前尽职地将其记录到标准错误。我不相信 SLF4J 会重定向 stderr,或者更改默认的异常处理程序;对于包括 throw new RuntimeException().

在内的任何异常,您都会得到相同的行为(跳过 SLF4J 并转到标准错误)

就修复而言,这取决于您要调整设置的深度:

  • 如果某些对象创建可能会失败,并且您希望应用继续 运行,您可能希望在 CreationException 中捕获 try/catch 块。然后您可以将日志消息传递给 SLF4J 并优雅地恢复。

  • 如果这是一个您不希望或不期望任何输入或输出控制台的程序,您可以通过 System calls 重置 stdin、stdout 和 stderr,但这可能被视为令人困惑且有些激烈。

  • this SO question 一样,您可以更改主线程的默认异常处理程序,以便将失败转到 SLF4J 而不是 stderr。但是,您可能仍然无法恢复:当您在线程中捕获异常时,没有其他地方可以恢复执行。