如何减少Java日志记录样板代码?

时间:2008-10-17 15:41:53

标签: java logging

每个想要使用java.util.logging的类通常都需要声明一个这样的记录器:

public class MyClass {
    private static Logger _log = Logger.getLogger(MyClass.class.getName());
}

如何避免使用此MyClass.class.getName()样板代码?

10 个答案:

答案 0 :(得分:12)

我在Eclipse中设置了一个模板,因此我只需要输入声明的一部分,然后Eclipse将自动为我完成其余部分。

${:import(org.apache.log4j.Logger)}
private final static Logger log = Logger.getLogger(${enclosing_type}.class);
${cursor}

所以,我只需要输入logger,点击Ctrl+Space,然后输入Enter,Eclipse会为我填写其余部分并添加导入声明。

这不会减少样板代码的数量,但至少会减少击键量。

答案 1 :(得分:4)

看一下在代码中使用切点

自从春天使用它们以来,我没有回头。

这是一篇关于使用AspectJ

的文章

http://www.developer.com/java/other/article.php/3109831

答案 2 :(得分:3)

根据您的日志记录需求,您可以创建一个“LoggingService”类,其中包含用于记录到各种“通道”的静态方法。我发现我真的不需要将粒度记录到类级别。您可以为记录器命名最适合您的方式。多年来,我们一直在大型企业应用程序中使用它,粒度对我们来说确实不是问题。

在静态初始化程序块中初始化日志记录服务...以便记录消息:

LoggingService.logError( “嗒嗒”);

每个班级都没有样板代码。

以下是一个示例日志记录服务:

public class LoggingService {

/**
 * A log for informational messages.
 */
static private Logger infoLog;

/**
 * A log for data access messages.
 */
static private Logger dataAccessLog;

/**
 * A log for debug messages.
 */
static private Logger debugLog;

/**
 * A log for error messages.
 */
static private Logger errorLog;

/**
 * A log for all XML related messages.
 */
static private Logger xmlLog;

/**
 * A log for all trace messages.
 */
static private Logger traceLog;

/**
 * A log for all warning messages.
 */
static private Logger warnLog;

static {

    //This is the bootstrap for the logging service.
    //Setup each logger
    infoLog = Logger.getLogger("com.company.logging.info");
    dataAccessLog = Logger.getLogger("com.company.logging.dataaccess");
    debugLog = Logger.getLogger("com.company.logging.debug");
    errorLog = Logger.getLogger("com.company.logging.error");
    xmlLog = Logger.getLogger("com.company.logging.xml");
    traceLog = Logger.getLogger("com.company.logging.trace");
    warnLog = Logger.getLogger("com.company.logging.warn");

    // This must be set so isErrorEnabled() will work.
    errorLog.setLevel(Level.ERROR);
    warnLog.setLevel(Level.WARN);
}
static public void logDataAccess(String pMessage) {
    dataAccessLog.info(pMessage);
}

static public void logInfo(String pMessage) {
    infoLog.info(pMessage);
}

static public void logDebug(String pMessage) {
    debugLog.debug(pMessage);
}

static public void logTrace(String pMessage) {
    traceLog.debug(pMessage);
}

static public void logWarn(String pMessage) {
    warnLog.warn(pMessage);
}

static public void logError(String pMessage) {
    errorLog.error(pMessage);
}

static public void logError(String pMessage, Throwable pThrowable) {
    errorLog.error(pMessage, pThrowable);
}

static public void logXml(String pMessage, XmlBean pContainer) {

    if (!xmlLog.isInfoEnabled()) return;

    xmlLog.info(pMessage + " : " + JAXBHelper.marshal(pContainer));
}

static public boolean isInfoEnabled() {
    return infoLog.isInfoEnabled();
}

static public boolean isDataAccessEnabled() {
    return dataAccessLog.isInfoEnabled();
}

static public boolean isDebugEnabled() {
    return debugLog.isDebugEnabled();
}

static public boolean isErrorEnabled() {
    if (errorLog.getLevel().toInt() >= Level.ERROR_INT) {
        return true;
    }
    return false;
}

static public boolean isTraceEnabled() {
    return traceLog.isDebugEnabled();
}

static public boolean isXmlEnabled() {
    return xmlLog.isInfoEnabled();
}

static public boolean isWarnEnabled() {
    return warnLog.isEnabledFor(Level.WARN);
}

}

答案 3 :(得分:3)

实际上,对记录器名称使用类名的常见做法是懒惰。

更好的做法是按任务上下文命名记录器。这涉及更多的思考过程和规划,但最终,结果更具有意义的粒度,您可以在其中切换实际任务而不是类的日志记录级别。

答案 4 :(得分:2)

如果您使用1.2版本的log4j,则不需要getName(),getLogger()接受Class参数。但至于其他方面,如果你希望每个类都有一个具有自己类别的静态日志成员,那么就没有办法解决它。

答案 5 :(得分:2)

如果你选择包级记录器,每个包添加一个样板类,你可以写:

private static final Logger log = Logs.log;

有些hacks可以读取调用者的类名(实际上日志记录实现有一个hack来检测当前方法),但我不建议这样做。

答案 6 :(得分:1)

您可以使用lombok

减少该许可和许多其他样板代码

https://github.com/rzwitserloot/lombok

 @Slf4j
     public class LogExample {
 }

将是

 public class LogExample {
     private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
 }

答案 7 :(得分:0)

你可以将这一点简写一下,因为getLogger过载也只需要上课。像这样:

public class MyClass {
    private static Logger _log = Logger.getLogger(MyClass.class);
}

Logger可以像你想要的一样灵活或不灵活。您可以为每个类获取一个新的记录器,如上例所示,并具有记录器层次结构,您可以在其中控制并按类打开/关闭日志记录。或者如果您的项目很小或原型等,您可以调用Logger.getRootLogger() - 但是您将失去微调您记录和不记录的灵活性。您可以拥有记录器所在的基类,让每个人都称之为基类,但同样,您会失去一些灵活性:

public class MyBase {
     protected static Logger _log = Logger.getLogger(MyClass.class);
}

public class MyClass extends MyBase {
    ....
    _log.info("Stuff....");
}

最重要的是,如果你想保持微调的能力,可以在项目的后期配置你的日志记录(只为一个类开启更精细的调试),那么你可能不得不在每个类中坚持使用样板。 / p>

答案 8 :(得分:0)

查看SLF4J

答案 9 :(得分:-1)

如果你使记录器非静态,你至少可以继承它:

public class SomeBaseClass
{
    protected Logger logger = Logger.getLogger(getClass());
}

public class SubClass extends SomeBaseClass
{
    public void doit() { logger.debug("doit!!!!"); }
}

这就是我一直以来的做法。