【问题标题】:Logger per instance, bad practice?每个实例的记录器,不好的做法?
【发布时间】:2019-08-04 23:43:56
【问题描述】:

我有一个类(例如 FileConfig),它在程序的许多不同位置使用,并且该类也是其(插件)API 的一部分。所以这个类应该是非常通用和广泛可用的。我想在这个类中使用Logger (java.util.logging.Logger)。如许多代码示例所示,每个类使用private static final Logger 实例似乎是最佳实践。在我看来,这在我的情况下非常不灵活。我可以想到我或使用 API 的人想要为程序的特定部分使用不同的 Logger 实例的情况。下面的代码展示了我解决这个问题的想法。

import java.util.logging.Logger;

public class FileConfig {
    private static final Logger LOGGER = Logger.getLogger(FileConfig.class.getName());
    private Logger logger = LOGGER;

    public void setLogger(Logger logger) {
        if (logger == null) {
            throw new IllegalArgumentException("logger cannot be null");
        }

        this.logger = logger;
    }
}

这使得每个实例可以使用不同的Logger,而默认行为仍然与仅使用static Logger 字段相同。这段代码有问题吗?我有理由避免这种情况吗?无论出于何种原因,这是不好的做法吗?如果是,为什么?我也非常感谢您对此的个人意见或建议如何改进它。

【问题讨论】:

  • 为什么要使用 JUL 而不是 slf4j?在什么确切情况下有人会想要使用不同的记录器?
  • 到目前为止我没有依赖项,也不需要它们。我不会仅将依赖项用于日志记录。使用 SLF4J 不能解决我的问题,记录器的使用方式与 JUL 记录器相同。我现在不能告诉你一个确切的情况,但它允许每个实例使用不同的记录器设置或名称。这个类的实例在完全独立的地方使用,所以我认为有不同的记录器是有意义的。它只是更灵活,这是我对普通课程的期望。
  • can't tell you an exact case:应用 YAGNI。听起来您真正想要的是多重诊断上下文 (MDC) 功能,这是使用 slf4j 之类的东西而不是 JUL 之类过时的东西的主要原因之一。 (如果你有 no 依赖项,那么要么你的代码非常简单,要么你正在重新发明很多轮子。)
  • 这没有帮助。您实际上对我的项目及其设置或复杂性一无所知。我问了一个非常具体的问题,我需要一个答案。

标签: java logging static instance java.util.logging


【解决方案1】:

这段代码有问题吗?

在使用记录器的线程和更改记录器的线程之间没有线程安全的协调。没有说明使用假设的 JavaDoc。

我有理由避免这种情况吗?

拥有可以在构造后调用的方法setLogger 可能允许消息在处理程序之间被撕裂。更改类的记录器似乎需要权限检查。

我也非常感谢您对此的个人意见或如何改进它的建议。

您不禁止子类,因此检查类名可能更安全:

import java.util.logging.Logger;

public class FileConfig {
    private final Logger logger = Logger.getLogger(getClass().getName());
}

想要使用不同记录器的调用者可以将“FileConfig”子类化。这允许在调用者的命名空间中创建子类,这通常是您在组合对象时想要实现的。

【讨论】:

  • 你如何看待有一个以 Logger 作为参数和一个私有的 final Logger 字段的构造函数。如果调用了另一个构造函数(或未提供 Logger),则该字段默认设置为 Logger.getLogger(getClass().getName())。
  • @stonar96 看起来也不错。
猜你喜欢
  • 1970-01-01
  • 2022-08-15
  • 1970-01-01
  • 2018-05-03
  • 1970-01-01
  • 1970-01-01
  • 2021-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多