如何使用log4j与多个类?

std*_*all 20 java log4j

我目前正在用java编写一个大项目,有很多类,有些类很小,只用很少的方法代表对象.我的主类中有一个记录器,它工作正常.我希望能够只使用一个记录器(带有一个控制台appender)和所有类.我试图将对记录器的引用传递给不同的类,但它看起来不正确.此外,有时候我在没有运行main的情况下对类运行测试,因此没有为其他类初始化记录器.

实现这一目标的最佳方法是什么,我的意思是,如何从不同的类登录到一个日志,类之间没有硬依赖关系,并且能够独立地使用每个类的日志?

Mat*_*ell 19

如果我理解正确的话,你现在所拥有的是:

public class Main {
    public static final Logger LOGGER = Logger.getLogger(Main.class);
}

public class AnotherClass {
    public void doSomething() {
        Main.LOGGER.debug("value=" + value);
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,将对记录器的引用传递给类的构造函数.

首先,您只需使用传递给Logger.getLogger的相同值即可使用一个全局记录器,如:

public class Main {
    private static final Logger LOGGER = Logger.getLogger("GLOBAL");
}

public class AnotherClass {
    private final Logger LOGGER = Logger.getLogger("GLOBAL");

    public void doSomething() {
        LOGGER.debug("value=" + value);
    }
}
Run Code Online (Sandbox Code Playgroud)

这使用完全相同的记录器,Logger.getLogger在两个调用中返回相同的对象.您不再在类之间具有依赖关系,这将起作用.

我从你的评论中收集的另一件事是你正在手动配置(使用 BasicConfigurator.configure.大多数情况下这不是必需的,你应该通过简单地将log4j.properties或log4j.xml添加到类路径来进行配置.在Eclipse中,这是通过将它添加到src /(或src/main/resources,如果你正在使用maven)来完成的.如果你正在使用junit,那么将它添加到test/source目录(或src/test/resources with maven).这是一个更好的配置log4j的长期方法,因为你不必在类之间传递信息.

此外,使用记录器的推荐方法是将类传递给Logger.getLogger().通过这种方式,您可以根据类名过滤输出,这通常比只有一个全局记录器更有用:

public class Main {
    private static final Logger LOGGER = Logger.getLogger(Main.class);
    public static final main(String[] args) {
        LOGGER.debug("started");
    }
}

public class AnotherClass {
    private final Logger LOGGER = Logger.getLogger(this.getClass());

    public void doSomething() {
        LOGGER.debug("value=" + value);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在log4j.properties中,您可以将单个appender配置为一个文件.

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
Run Code Online (Sandbox Code Playgroud)

最后,没有必要将所有记录器声明为静态.如果您正在进行大量 [*]对象创建,这只会产生明显的差异.将记录器声明为非静态字段允许您使用Logger.getLogger(this.getClass());在这种情况下向类添加记录器成为单行的剪切和粘贴.请参阅我是否应该声明日志引用是否为静态?(遗憾的是,维基页面的链接已被破坏),但slf4j页面也包含了很好的解释.所以使用非静态字段除非你有充分的理由不这样做.

当Cameron说你应该尝试使用slf4j时,它是正确的,它有一个杀手级功能,你可以使用多个日志框架.

[*]我的意思是很多.


Vin*_*lds 5

您的记录器实例通常应该是private,staticfinal.通过这样做,每个类将拥有它自己的记录器实例(在加载类后创建),这样您就可以识别创建日志记录的类,并且您不再需要跨类传递记录器实例.