Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是否值得在附加层中包装日志框架?_Java_Logging_Encapsulation_Slf4j_Apache Commons Logging - Fatal编程技术网

Java 是否值得在附加层中包装日志框架?

Java 是否值得在附加层中包装日志框架?,java,logging,encapsulation,slf4j,apache-commons-logging,Java,Logging,Encapsulation,Slf4j,Apache Commons Logging,我目前正在考虑升级中大型Java代码库中的日志机制。当前,消息是在Debug类上使用静态方法记录的,我建议从这个类切换到类似SLF4J或commons日志的类型 应用程序架构师希望我封装对SLF4J的依赖关系(可能通过将其封装在前面提到的Debug类中)。这将使将来更容易更改日志记录实现 这对我来说似乎有些过分,因为SLF4J已经在抽象具体的日志实现 像SLF4J这样的第三方日志抽象是否值得包装在另一个自主开发的抽象中?我完全同意你的看法:包装的包装正在失控。我怀疑架构师没有意识到SLF4J尤其

我目前正在考虑升级中大型Java代码库中的日志机制。当前,消息是在
Debug
类上使用静态方法记录的,我建议从这个类切换到类似SLF4J或commons日志的类型

应用程序架构师希望我封装对SLF4J的依赖关系(可能通过将其封装在前面提到的
Debug
类中)。这将使将来更容易更改日志记录实现

这对我来说似乎有些过分,因为SLF4J已经在抽象具体的日志实现


像SLF4J这样的第三方日志抽象是否值得包装在另一个自主开发的抽象中?

我完全同意你的看法:包装的包装正在失控。我怀疑架构师没有意识到SLF4J尤其可以轻松包装任何其他日志系统,因此“更改实现”是完全可行的,而无需另一层包装。

如果您考虑将来切换日志框架,可能值得添加一个额外的层,您可以在其中切换出记录器。否则,如果它们提供了您可能需要的一切(当然是使用水晶球),那么对该框架有一个硬依赖可能是可以的


如果您当前的设置允许灵活更改,则不需要包装器。

向您解释slf4j已经可以作为其他日志记录实现的包装器,如log4j。因此,如果您将来需要使用其他记录器,并且slf4j没有适配器,您可以在需要时编写它,但它只是适配器,与其编写一个完整的日志框架来包装其他日志框架,还不如为此设计框架并编写自己的适配器。

我更愿意包装它,但不是出于所述的原因。如果关注的是换成另一个框架的能力,请使用java.util.logging或SLF(java.util.logging不像包装器那么容易使用,但它是完全可行的),然后换掉。使用(另一个)包装器的原因是在代码中编码适当的日志记录方式。通常,应用程序需要一个子集,例如所有系统错误都有例外,或者对何时使用标准日志记录级别有特定的指导。这些决策可以封装在几个方法中,在大型代码库中创建更一致的日志决策

然而,如果动机仅仅是为了使替换实现成为可能,那么就不要重新发明轮子。SLF非常适合这项工作,只要使用它


这有一个例外。如果您的代码要部署到许多可能的应用程序服务器中,您必须确保您的日志选择不会与框架使用的任何版本的潜在旧版本或新版本发生冲突。

每个包装器的问题在于决定如何实际包装以及将提供哪些功能:

  • logging提供了一组最小的日志功能,隐藏了底层框架可能提供的其他功能。您将无法获得诸如参数化日志记录或MDC之类的高级功能
  • SLF4J的工作原理正好相反。它通过在非本机实现的框架之上实现参数化日志记录等高级功能来处理这些功能。这是更好的办法,伊姆霍
我不知道您当前的调试类,但我想它相当基本

你可能不会有这样的功能

  • 日志消息的位置,即源文件的名称+行号
  • 不同的日志记录级别
  • 能够有选择地设置不同记录器的级别,即每个类没有一个记录器,能够将该记录器设置为某个感兴趣的级别,例如INFO、WARN。这是非常关键的
如果您的调试类非常基本这实际上非常适合您:)

这意味着您可以通过执行全局搜索和销毁来切换到SLF4J。。。犯错误替换

但要做备份…;)


另见、和。(请不要使用java.util.logging)

我想架构师想要包装(即SLF4J)的动机是将应用程序与SLF4J隔离开来。显然,从应用程序内部调用SLF4J API会创建对SLF4J的依赖。然而,如下文所述,重复应用隔离原则同样合法。这让我想起理查德·道金斯的问题:如果上帝创造了宇宙,那么谁创造了上帝

实际上,您还可以在包装SLF4J的包装器上应用隔离原则。如果SLF4J包装器在某种程度上不如SLF4J,那么隔离的原因将是错误的。尽管有可能,但包装器与原始包装器相同或超过原始包装器的情况还是相当罕见的。SWT可以作为一个值得注意的反例。然而,SWT是一个规模庞大、成本高昂的项目。更重要的是,根据定义,SLF4J包装器依赖于SLF4J。它必然具有相同的通用API。如果将来出现一个新的、显著不同的日志API,那么使用包装器的代码将很难像直接使用SLF4J的代码一样迁移到新API。因此,包装器不太可能对您的代码进行未来验证,而是通过添加额外的间接寻址使其更重

简而言之,即使没有更好的事情要做,也不应该浪费时间包装SLF4J,因为包装的附加值保证接近于零

该主题也在一篇文章中提到。

重点是,SLF4J已经被设计成包装“任何可能的记录系统”(他们雄心勃勃,但也相当熟练……),并且已经提供了几个wr