Java日志框架,不需要在每个类上使用LOGGER声明

Edi*_*Edi 7 java logging log4j slf4j java.util.logging

我尝试了以下记录器

  • Java Logging API
  • Log4j的
  • SLF4J

所有这些都需要在类级别进行LOGGER声明,如下所示

private final static java.util.logging.Logger.Logger LOGGER = java.util.logging.Logger.Logger.getLogger(MyClass.class.getName());
private final Logger slf4jLogger = LoggerFactory.getLogger(SLF4JHello.class);
private final static Logger log4jLogger = Logger.getLogger(Log4jHello.class);
Run Code Online (Sandbox Code Playgroud)

这看起来很可怕,java中是否有一个不需要此声明的记录器框架?

我正在寻找的是,我可以有一个全球宣言

private final static Logger Logger = Logger.getLogger(MyApp.class);
Run Code Online (Sandbox Code Playgroud)

但是当我从类XXX.class 调用Logger.log(..)时,Logger应该使用XXX.class名称.

Oli*_*ire 2

您的问题很可能不在于日志记录框架,而在于布局。

具体例子

so35592962/App.java

package so35592962;
import org.apache.logging.log4j.*;
import so35592962.sub.OtherClass;
public class App {
  public static final Logger logger = LogManager.getLogger();
  public static void main(String[] args) {
    logger.error("in App.main");
    OtherClass.act();
  }
}
Run Code Online (Sandbox Code Playgroud)

so35592962/sub/OtherClass.java

package so35592962.sub;
import static so35592962.App.logger;

public class OtherClass {
  public static void act() {
    logger.error("OtherClass.act");
  }
}
Run Code Online (Sandbox Code Playgroud)

所以你可以看到这完全是你想要的:使用单个记录器的类。很好,Log4J2 可以用于此目的。

现在我添加魔法文件log4j2.xml

package so35592962;
import org.apache.logging.log4j.*;
import so35592962.sub.OtherClass;
public class App {
  public static final Logger logger = LogManager.getLogger();
  public static void main(String[] args) {
    logger.error("in App.main");
    OtherClass.act();
  }
}
Run Code Online (Sandbox Code Playgroud)

运行此命令将打印:

package so35592962.sub;
import static so35592962.App.logger;

public class OtherClass {
  public static void act() {
    logger.error("OtherClass.act");
  }
}
Run Code Online (Sandbox Code Playgroud)

看,这里有不同的类名!但我使用的是 Log4J2。

这里发生了什么?

请注意标签中使用的模式PatternLayout

%d{HH:mm:ss.SSS} [%t] %-5level %C{36} - %msg%n

标准示例和您通常在互联网上看到的都使用该%L模式。此模式用于显示记录器名称。但你说过你不想要它。幸运的是,还存在其他模式。%C将显示类名称而不是记录器名称。这是这里使用的模式。

根据文档PatternLayout,该%C模式执行以下操作

输出发出日志记录请求的调用者的完全限定类名。

重要提示,文档中也提到:

生成调用者的类名(位置信息)是一项昂贵的操作,并且可能会影响性能。谨慎使用。

  • 另外,这个答案不是“是的,无论如何,这样做”,而是“您的请求可以完成,具体方法如下”。我个人并不赞同这一点,但如果我为OP工作,我很高兴我能提供帮助! (3认同)