Singleton记录器持有多个参考

时间:2014-10-09 18:12:07

标签: java design-patterns logging singleton log4j2

我有一个使用log4j2的Singleton Logger,它将从各种类中调用。 输出格式为 - 日期INFO com.so.pg1 abc

说我有4个类(第1页,第2页,第3页,第4页)。我目前正在使用pg4类,它在内部声明了pg1,pg2,pg3。 所有这些都有一个私人记录器字段。

private static SingletonLog logger = SingletonLog.getInstance(pg4.class.getName());

他们所有的方法都包含 log.info(),我将日志记录级别设置为 INFO 。 我需要一种方法来确保每次pg1调用log.info(" abc"), 输出应该看起来像日期INFO com.so.pg1 abc 。 并且pg2调用log.info(" xyz")输出应该看起来像 date INFO com.so.pg2 xyz 。 但是现在所有的日志都有相同的类名com.so.pg3,如下所示。

各种记录器引用应该由SingletonLog类实现处理,并且对于调用类应该是无缝的。

请帮我纠正这个问题。

示例代码:

public class pg4 {
  private static SingletonLog logger = SingletonLog.getInstance(pg4.class.getName());

  pg1 two = new pg1();
  pg2 two = new pg2();
  pg3 two = new pg3();

  public void methodA() {
    logger.setLevel(INFO);
    logger.info("efg");
    pg1.methodB();  //This too has SingletonLog field with p1.class.getName() as input.
    pg2.methodC();  // same as above
    pg3.methodD();  // same as above
  }
}

public class SingletonLog {
  private static Logger internalLog = null;
  private static SingletonLog uniqueInstance = null;

  public getInstance(String className) {
    if (uniqueInstance == null)
        uniqueInstance = new unique();
    internalLog = LogManager.getLogger(className);
    return uniqueInstance;
  }
}

Expected Output for this code:
<date> INFO com.so.pg4 efg
<date> INFO com.so.pg1 abc
<date> INFO com.so.pg2 xyz
<date> INFO com.so.pg3 mno

Actual Output: 
<date> INFO com.so.pg3 efg
<date> INFO com.so.pg3 abc
<date> INFO com.so.pg3 xyz
<date> INFO com.so.pg3 mno

1 个答案:

答案 0 :(得分:0)

Singleton会阻止您获得所需的输出。

第一次调用Singleton.getInstance(“a.b.c”)时,会使用FQCN(完全限定类名)“a.b.c”创建记录器。此记录器被缓存,下次调用Singleton.getInstance(“x.y.z”)时,它将返回缓存的相同(a.b.c)实例。一旦创建并缓存了记录器,getInstance()方法将忽略指定的FQCN。

解决方案是不使用单身人士。

Log4j已在内部缓存Loggers。如果您从某个地方拨打LogManager.getLogger("a.b.c"),然后再从另一个地方拨打LogManager.getLogger("a.b.c"),您将获得相同的 Logger实例。但是,如果您从另一个地方拨打LogManager.getLogger("x.y.z"),则会获得不同的 Logger实例。这是正常用法,我相信这可以满足您的需求。它将导致您在“预期输出”下显示的输出。