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

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

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

你如何避免这个MyClass.class.getName()样板代码?

我在Eclipse中设置了一个模板,所以我只需要输入声明的一部分,然后Eclipse会自动为我完成剩下的部分。

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

所以,我只需要键入loggerCtrl+Space ,然后按Enter ,Eclipse会为我填写其余部分并添加导入声明。

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

看看在代码中使用切点

自从spring使用它们以来我一直没有回头。

这是一篇关于使用AspectJ的文章

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

根据您的日志记录需求,您可以创建一个“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); } 

}

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

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

如果您使用1.2版本的log4j,则不需要getName(),getLogger()接受Class参数。 但至于其余部分,如果您希望每个类都有一个具有自己类别的静态日志成员,则没有任何方法。

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

 private static final Logger log = Logs.log; 

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

你可以用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); } 

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

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

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

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

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

看看SLF4J吧

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

 public class SomeBaseClass { protected Logger logger = Logger.getLogger(getClass()); } public class SubClass extends SomeBaseClass { public void doit() { logger.debug("doit!!!!"); } } 

这就是我一直这样做的方式。