Java 从log4j.Logger获取记录器的通用方法

Java 从log4j.Logger获取记录器的通用方法,java,log4j,Java,Log4j,不要在每个类上指定类名: log = Logger.getLogger(Foo.class); log = Logger.getLogger(Bar.class); log = Logger.getLogger(Test.class); 是否可以使用: log = Logger.getLogger(this.getClass()); 这意味着什么呢?肯定没问题 请注意,其中一个含义是,如果您在静态上下文中使用日志时遇到问题-它可能未初始化或不可见如果您创建子类,日志消息将被记录到子类的记录器

不要在每个类上指定类名:

log = Logger.getLogger(Foo.class);
log = Logger.getLogger(Bar.class);
log = Logger.getLogger(Test.class);
是否可以使用:

log = Logger.getLogger(this.getClass());
这意味着什么呢?

肯定没问题


请注意,其中一个含义是,如果您在静态上下文中使用日志时遇到问题-它可能未初始化或不可见

如果您创建子类,日志消息将被记录到子类的记录器中

package pkgone;
public class SuperType {
    private Logger log = Logger.getLogger(this.getClass());
    public void someAction() {
        log.info("Doing something");
    }
}


在上面的示例中,“Doing something”将被记录到pkgtwo.SubType记录器,而不是pkgone.SuperType记录器,这可能是您想要的,也可能不是您想要的。

据我所知,没有任何影响。根据Matt的评论,我想这是每个人都想要的正确行为。

+1对于调用超级方法的子类实例,记录器将是子类


另外,如果您将此应用为类的日志模板,如果您的类是抽象的,那么您的this.getClass将失败,因为您没有此类的实例。

使用Apache commons的日志工厂:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Logger;

public class SomeNewClass {
...
private final Log logger = LogFactory.getLog(this.getClass());
...
}
不必做任何其他事情。不确定LogFactory在发布问题时是否可用。 如果您不想使用LogFactory,也可以简单地将private final与getClass()一起使用


没有理由创建子类,除非您希望获得日志的继承权,这也可以通过操纵日志配置文件(log4j.xml,如果您正在使用)来完成。当记录器被定义为静态时,就不能使用这个.getClass()。如果没有static或private final,您会让记录器面临您不想要的危险的可能更改

如果您不想重复创建
记录器,也不想写入错误的类名,那么就没有必要了

如果您不介意在项目中再使用一个库,您可以简单地添加一个带有简单注释的记录器

import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;

@Log
public class LogExample {    
  public static void main(String... args) {
    log.error("Something's wrong here");
  }
}

尝试用这种方法查找泛型类

private static final Log LOGGER = Logger.getLogger(MethodHandles.lookup().lookupClass());

最好的部分是您可以静态地使用此方法。

公共最终类AppLogger{

private AppLogger() {
}


public static final void logInfo(Class<?> clazz, String logMessage) {
    Logger logger = Logger.getLogger(clazz);
    if (logger.isInfoEnabled()) {
        logger.info(logMessage);
    }
}

public static final void logInfo(Class<?> clazz, String logMessage, Throwable th) {
    Logger logger = Logger.getLogger(clazz);
    if (logger.isInfoEnabled()) {
        logger.info(logMessage, th);
    }
}
private AppLogger(){
}
公共静态最终void logInfo(类clazz,字符串logMessage){
Logger=Logger.getLogger(clazz);
如果(logger.IsInfo已启用()){
logger.info(logMessage);
}
}
公共静态最终void logInfo(类clazz、字符串logMessage、Throwable th){
Logger=Logger.getLogger(clazz);
如果(logger.IsInfo已启用()){
logger.info(logMessage,th);
}
}
}

创建该类,然后将其添加到调用类中。
Applogger.logInfo(Class.Class,String变量)

这是我没有想到的事情!谢谢如果它是:Logger.getLogger(SuperType.class),那么会有什么区别@user648026然后对该日志对象的日志记录请求将转到
pkgone.SuperType
记录器。也就是说,无论它是什么子类,在上面的示例中,日志消息都将转到该记录器。在我看来,这是一个比较容易混淆的规则,因为你确切地知道它将使用哪个记录器。但在某些情况下,您可能希望SuperType的日志记录请求转到子类型的日志,可能是因为您有多个子类,并且希望根据子类对日志消息进行分类。请参阅matts comment以了解一个可能的含义。它是否这样做。getClass()或ClassName.class?@Vikash根据文档,是后者。
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;

@Log
public class LogExample {    
  public static void main(String... args) {
    log.error("Something's wrong here");
  }
}
private static final Log LOGGER = Logger.getLogger(MethodHandles.lookup().lookupClass());
private AppLogger() {
}


public static final void logInfo(Class<?> clazz, String logMessage) {
    Logger logger = Logger.getLogger(clazz);
    if (logger.isInfoEnabled()) {
        logger.info(logMessage);
    }
}

public static final void logInfo(Class<?> clazz, String logMessage, Throwable th) {
    Logger logger = Logger.getLogger(clazz);
    if (logger.isInfoEnabled()) {
        logger.info(logMessage, th);
    }
}