slf4j和logback的简单介绍
关于slf4j的介绍很多,文本不再多言,在笔者看来,slf4j主要解决两个问题,通过下面具体事例来说明。
1.我们正在开发一个bar.jar组件,并且使用了common-logging作为日志,这种情况下,使用我们组件的第三方程序也不得不引入了common-logging,为了让common-logging能正常的工作,第三方的程序也不得加一些额外的配置,显然,第三方程序不太喜欢这种方式。
slf4j这样的日志组件正是为了解决这个问题,其解决思路是:开发时面向日志的标准接口,具体使用何种日志实现留给最终的组件调用者。像上面的例子是,开发bar.jar时使用slf4j的日志标准,而不引用任何一种实现,第三方程序需要用到bar.jar再决定使用何种具体的实现。目前使用这种“标准-实现”的日志框架中,sfl4j的使用最为广泛,slf4j提供了一个日志实现logback,另外,为了能兼顾众多的具体日志实现,slf4j支持了commons-logging,log4j,log4j2等。
2.我们的项目引入了一个组件,例如叫做foo.jar,foo.jar使用了log4j作为其日志,而我们自己的项目使用slf4j+logback作为日志的解决方式,那么这样一来,项目中继承了foo.jar所依赖的log4j, 而且foo.jar中日志很可能无法正常的运行,不会将日志写到为logback配置的日志文件中。
为了解决这个问题,slf4j提供了adapter的方式用一个伪装的组件替换掉了这些日志组件(本人认为这是适配器模式一个很好的例子),这个伪装的日志组件将日志导向了slf4j的具体实现,在上面的例子里,是将log4j导向了logback,对于常见的commons-logging,log4j,java.util.logging, slf4j都提供了adapter,对于slf4j没有提供adapter的日志组件,也可以根据其标准自己编写。
以上是slf4j和logback的简单介绍,下面着重介绍在maven中的配置。
在maven中的配置
1.加入标准和实现
首先,在pom.xml中加入sfl4j的标准和使用实现,这里使用logback作为具体实现,具体如下:
|
|
2.针对其他依赖引入的log组件,加入slf4j adapter,并排除其原有依赖
以spring-core为例,其使用commons-logging作为日志组件,组需要加入slf4j commons-logging adapter,还需要将spring-core的commons-logging依赖排除
|
|
像cassandra-all这样的组件更要注意,因为其不仅依赖了第三方日志,还依赖了slf4j的其他实现,下面这例子中,如果不排除掉slf4j-log4j12,logback有可能会被顶替掉,slf4j会采用在classpath中找到的第一个符合slf4j实现的日志组件。
总结起来说,当引入一个新的组件时,我们要仔细的检查其依赖的日志组件,检查的要点有这么两个
- 如果其依赖了log4j,commons-logging,java.util,需要将其排除,并加入对应的adapter
- 如果依赖了slf4j及其实现,需要全部排除
3.一个”一劳永逸”的解决方式
像是上面这种每次引入新的依赖都要检查日志组件和adapter的方式确实有些麻烦,可以在一开始的时候就在pom.xml中加入slf4j提供的所有adapter,并且使用maven-enforcer-plugin这个maven插件禁止除了logback之外的slf4j实现。一个比较完整的写法如下
|
|
注意maven-enforcer-plugin的作用不是全局排除依赖,而是一个保险机制:检查依赖是否存在,如果存在,则构建失败。
当然,这种方式也是有缺点的:一是有可能引入一些没用的依赖,第二,如果引入了一个不是slf4j提供的、而是自定义的slf4j实现,依然会导致和logback的冲突。
写到这里本文差不多结束了,敲这些字的过程中不禁想,一个简单的log组件的配置想搞明白也不是那么简单,开发软件,其实真是挺难的。