Java 每个实例的日志记录程序,错误的做法?

Java 每个实例的日志记录程序,错误的做法?,java,logging,static,instance,java.util.logging,Java,Logging,Static,Instance,Java.util.logging,我有一个类(例如FileConfig),它在程序中的许多不同位置使用,该类也是其(插件)API的一部分。因此,该类应该非常通用,并且具有广泛的可用性。我想在这个类中使用记录器(java.util.logging.Logger)。如许多代码示例所示,在每个类中使用私有静态最终记录器实例似乎是最佳实践。在我看来,就我而言,这是非常不灵活的。我可以想到我或使用API的人希望为程序的特定部分使用不同的记录器实例的情况。下面的代码显示了我解决这个问题的想法 import java.util.logging

我有一个类(例如FileConfig),它在程序中的许多不同位置使用,该类也是其(插件)API的一部分。因此,该类应该非常通用,并且具有广泛的可用性。我想在这个类中使用
记录器
java.util.logging.Logger
)。如许多代码示例所示,在每个类中使用
私有静态最终记录器
实例似乎是最佳实践。在我看来,就我而言,这是非常不灵活的。我可以想到我或使用API的人希望为程序的特定部分使用不同的
记录器
实例的情况。下面的代码显示了我解决这个问题的想法

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;
    }
}
这使得每个实例可以使用不同的
记录器
,而默认行为仍然与只有
静态记录器
字段相同。这个代码有什么问题吗?我有什么理由避免这样做吗?这种坏习惯是出于什么原因?若有,原因为何?我也会很感激你的个人意见或建议如何改善它

这个代码有什么问题吗

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

我有什么理由避免这样做吗

如果在构造后可以调用方法
setLogger
,则可能会允许在处理程序之间删除消息。更改类的记录器似乎需要权限检查

我也会很感激你的个人意见或建议如何改善它

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

import java.util.logging.Logger;

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

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

为什么要使用JUL而不是slf4j?在什么样的情况下,有人会希望使用不同的记录器?到目前为止,我没有依赖项,也不需要它们。我不会将依赖项仅用于日志记录。使用SLF4J无法解决我的问题,记录器的使用方式与JUL记录器相同。我现在无法告诉您确切的情况,但它允许使用不同的记录器设置或每个实例的名称。在完全独立的地方使用了这个类的实例,所以在我看来,使用不同的记录器是有意义的。它只是更灵活,这是我对普通类的期望。
无法告诉您确切的情况:Apply YAGNI。听起来你真正想要的是一个多诊断上下文(MDC)功能,这是使用像slf4j这样的东西而不是像JUL这样过时的东西的主要原因之一。(如果你没有依赖项,那么你的代码可能是难以置信的微不足道,或者你正在重新发明很多轮子。)这是没有帮助的。实际上,你对我的项目及其设置或复杂性一无所知。我问了一个非常具体的问题,我需要一个答案。你觉得有一个以记录器为参数的构造函数和一个私有的最终记录器字段怎么样。如果调用了另一个构造函数(或未提供记录器),则默认情况下该字段设置为Logger.getLogger(getClass().getName())。@stonar96这似乎也不错。