【问题标题】:Singleton logger holding multiple references持有多个引用的单例记录器
【发布时间】:2014-10-13 18:28:48
【问题描述】:

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

假设我有 4 个类(pg1、pg2、pg3、pg4)。我目前正在使用内部声明 pg1、pg2、pg3 的 pg4 类。 它们都有一个私有的记录器字段。

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

他们所有的方法都有log.info(),我将日志级别设置为INFO。 我需要一种方法来确保每次 pg1 调用 log.info("abc"), 输出应该类似于 date 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

【问题讨论】:

  • 我认为您发布的代码甚至无法编译,请考虑更新它。
  • 这不是完整的代码。我发布它是为了让人们更好地理解我的陈述。
  • 我了解到您还没有发布完整的代码@deepng,我认为您选择这样做是件好事。 private static logger logger = null; 行看起来在编译时会失败,因为您没有指定类型。如果代码(在应用程序的上下文中)确实可以编译,请考虑遵循 Java 的命名约定,因为这将使其他开发人员更容易提供帮助! Class names uses CamelCase
  • 当然,吉姆。下次我发布一些东西时,我会记住这一点。谢谢。

标签: java design-patterns logging singleton log4j2


【解决方案1】:

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

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

解决办法是不使用单例。

Log4j 已经在内部缓存了 Logger。如果您从某个地方调用LogManager.getLogger("a.b.c"),然后再次从另一个地方调用LogManager.getLogger("a.b.c"),您将获得相同 Logger 实例。但是,如果您从另一个地方调用LogManager.getLogger("x.y.z"),您将获得一个不同 Logger 实例。这是正常用法,我相信这正是您想要的。它将导致您在“预期输出”下显示的输出。

【讨论】:

  • 太棒了。做了我想要的。谢谢雷姆科。
猜你喜欢
  • 1970-01-01
  • 2017-10-21
  • 2023-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多