如何正确初始化记录器?

Chr*_*olf 6 java logging java.util.logging

我有以下问题:我想使用java.util.logging.Logger.没有我发现不同的资源,1,2,3,如何能够修改记录的行为.

特别是在2 a(在我看来)的问题中,给出了根据类名初始化记录器的良好结构.如果需要,这还允许在基于包的级别上修改详细程度以进行调试.

经过一番深入研究后发现,全局记录器和"空"记录器(带名称"")不一样.另请参见下面的示例.我刚刚创建了一个记录器foo.Bar,它锚定在空记录器而不是被调用的记录器上foo.只有在我第一次创建记录器时bar,记录器bar.Baz才会正确锚定.

这使得这个问题中的方法主要无用,因为我们不能假设之前创建的父记录器.根据需要,我必须根据需要解析类名并创建记录器.

我是否正确我必须添加一些static {...}代码以递归方式初始化记录器,然后才能初始化自己的记录器?如果多个类调用Logger.getLogger(String)包记录器的方法(导致总体上多次调用,例如两者bar.Bazbar.FooBaz获取记录器bar),这会产生任何负面影响吗?

import java.util.Enumeration;
import java.util.logging.LogManager;
import java.util.logging.Logger;
public class TestLogger
{
    public static void main(String[] args)
    {
        // Create the logger directly
        Logger.getLogger("foo.Bar");
        // Create the logger objects step-by-step
        Logger.getLogger("bar");
        Logger.getLogger("bar.Baz");
        // Put the available loggers to output
        Enumeration<String> e = LogManager.getLogManager().getLoggerNames();
        while(e.hasMoreElements())
        {
            String s = e.nextElement();
            Logger l = Logger.getLogger(s);
            String p = (l.getParent() == null ? "none" : "'" + l.getParent().getName() + "'");
            System.out.println("'" + s + "': " + p);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

该程序的输出是

'bar': ''
'global': ''
'foo.bar': ''
'bar.baz': 'bar'
'': none
Run Code Online (Sandbox Code Playgroud)

Gav*_*iel 1

在每个类中都有一个负面影响Logger.getLogger(String)是您将无法模拟它(或通过特殊的记录器)进行测试。

示例:假设您需要测试以下 C 类:

package a.b;
class C {
  private Logger logger;
  private int capacity;
  private int size;
  C(int capacity) {
    this.logger = Logger.getLogger("a.b.C");
    this.capacity = capacity;
    size = 0;
  }
  void add(int item) {
    if (size >= capacity) {
      logger.log("You already reached the capacity: " + capacity);
    }
    //...
  }
}
Run Code Online (Sandbox Code Playgroud)

要求达到容量后添加日志。现在你需要测试它。进行测试来测试这一点是非常困难和困难的:

public void testCapacityReachedLogs() {
    C c = new C(2);
    c.add(1);
    c.add(2);
    // verify that c logged the exact string: "You already reached the capacity: 2"
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您有:

package a.b;
class D {
  private Logger logger;
  private int capacity;
  private int size;
  D(Logger logger, int capacity) {
    this.logger = logger;
    this.capacity = capacity;
    size = 0;
  }
  void add(int item) {
    if (size >= capacity) {
      logger.log("You already reached the capacity: " + capacity);
    }
    //...
  }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以模拟 Logger:

public void testCapacityReachedLogs() {
    Logger logger = getMock(Logger.class);
    D d = new D(logger, 2);
    d.add(1);
    d.add(2);
    verify(logger).log("You already reached the capacity: 2");
}
Run Code Online (Sandbox Code Playgroud)

请注意,“模拟”相关代码不一定遵循框架的语法,它只是作为示例。