常见的日志框架及日志门面 常见日志门面:JCL、slf4j 常见日志实现:JUL、log4j、logback、log4j2 框架诞生顺序:log4j --> JUL --> JCL --> slf4j --> logback --> log4j2 日志门面和日志实现的关系 一、JCL 1、JCL简介 全称为Jakarta Commons Logging,是Apache提供的一个通用日志API common-logging jdk自带的jul 使用它的好处就是,代码依赖是common-logging而非log4j的API, 避免了和具体的日志API直接耦合,在有必要时,可以更改日志实现的第三方库(不改变代码,只修改依赖) JCL 有两个基本的抽象类:Log(日志记录器),LogFactory(日志工厂负责创建Log实例) 2、快速入门 jcl依赖 <dependency> <groupId>commons-logging 原理 通过LogFactory动态加载Log实现类 Jdk14Logger就是jdk自带JUL日志框架(因为JUL从jdk1.4开始提供) SimpleLog是日志门面JCL自带日志,功能简单一般不用
从源码的角度讲述了 Spring Boot 的 LoggingSystem 与日志组件的绑定,默认情况下绑定的是 Logback;但当我们具体去看 Spring Boot 的日志打印,却发现用的是 spring-jcl private static final Logger LOGGER = LoggerFactory.getLogger(TestWeb.class); 还是 Spring Boot 用的 spring-jcl LoggerContext,其中包括 LoggerContext 的 objectMap,然后重新加载日志配置文件内容到 LoggerContext 的 objectMap中 所以甭管是使用 spring-jcl ,还是使用 slf4j 进行的日志打印,用到的 Appenders 都是 Spring Boot 启动过程中从日志配置文件中加载的,那么 spring-jcl 与 LoggingSystem 有什么关系 > logback-spring.xml 寻找日志配置文件 正因为 Spring Boot 启动过程中会重新加载日志配置文件内容到 LoggerContext,所以不管是 spring-jcl
JCL 与 JUL 集成 从前面分析可知, JCL 通过自动发现,即可完成与 JUL 的集成; POM 配置:只需要引入JCL; <dependency> <groupId>commons-logging JCL 与 Log4j1 集成 从前面分析可知, JCL 通过自动发现,即可完成与 Log4j1 的集成,且自动发现的优先级最高; POM配置:引入 JCL 和 Log4j1.x; <dependency JCL 与 Log4j2 集成 从前面分析可知, JCL 自身没有 Log4j2 的适配器,所以引入 Log4j2 提供的 JCL 适配器。 log4j-jcl 通过 SPI 形式,控制 JCL 使用 log4j-jcl 中的 LogFactory 的实现类 org.apache.logging.log4j.jcl.LogFactoryImpl JCL 与 Logback 集成 JCL 自身没有到 Logback 的适配器; Logback 默认实现的是 SLF4J 接口,通过 SLF4J-API 访问; 所以 JCL 需要将日志记录请求中转给
目前用的最广泛的日志门面有两种:SLF4J 和 Apache Commons Logging(JCL)。 与 slf4j-jcl.jar 对比; JCL-over-SLF4J, i.e. jcl-over-slf4j.jar, comes in handy in situations where JCL Indeed, slf4j-jcl.jar will delegate all logging decisions to JCL so that the dependency on SLF4J API Please note that jcl-over-slf4j.jar and slf4j-jcl.jar cannot be deployed at the same time. ; } } 运行结果: POM 依赖:将 JUL、JCL 的调用都通过 SLF4J 转发给 Log4j2; <!
日志框架总结 日志框架分为三大部分: 日志门面(例如:jcl、slf4j) 日志适配器 日志门面->日志库适配器(例如:slf4j-log4j12); 日志库->日志门面适配器(例如:log4j-over-slf4j ); 日志门面->日志门面适配器(例如:jcl-over-slf4j); 日志库(例如:log4j、logback) 1.1. 各种日志 JAR 包梳理 3. spring-jcl 项目源码分析 3.1. spring-jcl 与 jcl 的关联 不管怎样,当 jcl 与 spring-jcl 共存时,最终进行日志服务发现的肯定是 spring-jcl; 3.2. spring-jcl 的服务发现策略 感兴趣可以继续深入研究 参考: 《码出高效:Java 开发手册》 《Java 开发手册 1.5.0》
(Simple Logging Facade for Java,缩写Slf4j) JCL原理 JCL依赖包 <dependency> <groupId>commons-logging</groupId void jcl(){ Log logger = LogFactory.getLog("a"); logger.info("jcl"); } JCL核心代码 //这是JCL的最后发布版本中内置的四种日志技术 -- jcl 绑定器--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jcl</artifactId --jcl桥接器--> <dependency> <groupId> org.slf4j</groupId> <artifactId> jcl-over-slf4j</artifactId JCL,所以在有log4j的时候使用log4j打印日志,没有的时候使用JUL打印日志 spring5日志体系,大体结构没变,只是原来common-logging,换成了spring-jcl,看名字就知道是
diary_report.jpg What did you do today 日志门面有:jcl(Apache Commons Logging), slf4j, jboss-logging(不是服务大众的 jcl: commons-logging包含jcl的全部原生内容,log4j-jcl是jcl到log4j2的桥梁,jcl-over-slf4j是jcl到slf4j的桥梁。 slf4j-jcl: slf4j到jcl的桥梁。 如果某一个实际的日志框架转向slf4j。 jul-to-slf4j:jul适配slf4j。 jcl-over-slf4j:apache common logging适配slf4j。 ?
作者丨张丰哲 https://www.jianshu.com/p/127d3201921b 日志框架漫谈 Java平台下存在很多日志框架,比如JUL(java.util.logging),JCL 其次,我们要注意一个问题,由于在项目开发中,不可避免需要引入其他依赖,比如Spring默认使用的是commons-logging(即JCL),而Hibernate默认使用的是jboss-logging, 上图中的右侧部分就揭示了方法,打个比方,如果我们依赖Spring,虽然Spring默认使用的是JCL,要想在项目中统一使用slf4j+logback的话,很简单,我们先排除掉 JCL的依赖,然后再引入jcl-over-slf4j.jar (其实就是在偷梁换柱,jcl-over-slf4j.jar和JCL在包名/类名/方法名上完全一致,只不过jcl-over-slf4j在内部调用的是slf4j的api而已,这样既可以避免Spring报错, 上文说过Spring默认的日志依赖是JCL,而SpringBoot肯定是依赖Spring的,根据上文理论,自然是需要排除掉JCL的依赖的,我们来看下面的: ?
SpringBoot对日志的支持,讲解Java平台下日志的那些事,彻底揭开日志框架在使用过程中的那些坑~ 日志框架漫谈 Java平台下存在很多日志框架,比如JUL(java.util.logging),JCL 其次,我们要注意一个问题,由于在项目开发中,不可避免需要引入其他依赖,比如Spring默认使用的是commons-logging(即JCL),而Hibernate默认使用的是jboss-logging, 上图中的右侧部分就揭示了方法,打个比方,如果我们依赖Spring,虽然Spring默认使用的是JCL,要想在项目中统一使用slf4j+logback的话,很简单,我们先排除掉 JCL的依赖,然后再引入jcl-over-slf4j.jar (其实就是在偷梁换柱,jcl-over-slf4j.jar和JCL在包名/类名/方法名上完全一致,只不过jcl-over-slf4j在内部调用的是slf4j的api而已,这样既可以避免Spring报错, 上文说过Spring默认的日志依赖是JCL,而SpringBoot肯定是依赖Spring的,根据上文理论,自然是需要排除掉JCL的依赖的,我们来看下面的: ?
为了解决这个问题,Apache Commons Logging (之前叫 Jakarta Commons Logging,JCL)粉墨登场,JCL 只提供 log 接口,具体的实现则在运行时动态寻找。 这样一来组件开发者只需要针对 JCL 接口开发,而调用组件的应用程序则可以在运行时搭配自己喜好的日志实践工具。 所以即使到现在你仍会看到很多程序应用 JCL + log4j 这种搭配,不过当程序规模越来越庞大时,JCL的动态绑定并不是总能成功,具体原因大家可以 Google 一下,这里就不再赘述了。 , jcl, nop 等,他们实现了跟具体日志工具(比如 log4j)的绑定及代理工作。 )把他们的日志输出重定向到 SLF4J,所谓的桥接器就是一个假的日志实现工具,比如当你把 jcl-over-slf4j.jar 放到 CLASS_PATH 时,即使某个组件原本是通过 JCL 输出日志的
也是依赖了JCL。 ,确实更加优雅,但是由于之前很多代码库已经使用JCL,虽然出现slf4j和JCL之间的桥接转换,但是集成的时候问题依然多多,对很多新手来说确实会很懊恼,因为比单独的log4j时代“复杂”多了,抱怨声确实很多 为了使使用JCL等等其他日志系统后者实现的用户可以很简单地切换到slf4j上来,给出了各种桥接工程,比如:jcl-over-slf4j会把对JCL的调用都桥接到slf4j上来,可以看出jcl-over-slf4j 的api和JCL是相同的,所以这两个jar是不能共存的。 JCL(commons-logging) 由于项目的日志打印必然选择两个框架中至少一个,这时候,Apache的JCL(commons-logging)诞生了。
常见的日志门面 : JCL、slf4j 常见的日志实现: JUL、log4j、logback、log4j2 日志框架出现的历史顺序: log4j —> JUL—> JCL—> slf4j —> logback > <AppenderRef ref="serverlog"/> </AsyncRoot> </Loggers> </Configuration> 四、JCL 他允许开发人员使用不同的具体日志实现工具: Log4j, Jdk 自带的日志(JUL) JCL 有两个基本的抽象类:Log(基本记录器)和LogFactory(负责创建Log实例)。 日志记录器对象 Log log = LogFactory.getLog(JCLTest.class); // 日志记录输出 log.info("hello jcl
jcl日志引入到SLF4J上,添加依赖包jcl-over-slf4j.jar,否则可能Spring框架的日志无法输出到日志文件中。 JCL已慢慢淡出人们的视线,一些历史遗留项目也开始慢慢由JCL转向SLF4J,如:Spring 5.0开始没有再依赖原生的JCL框架,SpringBoot默认采用SLF4J+Logback。 SLF4J已经成为了Java日志组件的明星选手,可以完美替代JCL,使用JCL桥接库也能完美兼容一切使用JCL作为日志门面的类库,现在的新系统已经没有不使用SLF4J作为统一日志API接口层的理由了。 核心原理 SLF4J和JCL对比,二者最大区别在于它们的绑定机制的不同,这也决定了为什么JCL会被慢慢的淘汰掉的根本原因。 JCL绑定原理 JCL采用动态绑定机制,缺点是容易引发混乱,在一个复杂甚至混乱的依赖环境下,确定当前正在生效的日志服务是很费力的,特别是在程序开发和设计人员并不理解JCL的机制时。
这个时候jcl(Jakarta Commons Logging)出现了,说jcl可能大家有点陌生,讲commons-logging-xx.jar组件,大家总有印象吧。 JCL 只提供 log 接口,具体的实现则在运行时动态寻找。这样一来组件开发者只需要针对 JCL 接口开发,而调用组件的应用程序则可以在运行时搭配自己喜好的日志实践工具。 JCL可以实现的集成方案如下图所示 ? jcl默认的配置:如果能找到Log4j 则默认使用log4j 实现,如果没有则使用jul(jdk自带的) 实现,再没有则使用jcl内部提供的SimpleLog 实现。 spring默认使用的是jcl输出日志,由于你此时并没有引入Log4j的日志框架,jcl会以jul做为日志框架。此时集成图如下 ?
Apache见此,开发了JCL(Jakarta Commons Logging),即commons-logging-xx.jar。它只提供一套通用的日志接口api,并不提供日志的实现。 这样看上去也挺美好的,但是log4j的作者觉得JCL不好用,自己开发出slf4j,它跟JCL类似,本身不替供日志具体实现,只对外提供接口或门面。目的就是为了替代JCL。 JCL commons-logging已经停止更新,最后的状态如下所示: ? 其实总的来说,无论就是以下几种情况 你在用JCL 使用jcl-over-slf4j.jar适配 你在用log4j 使用log4j-over-slf4j.jar适配 你在用JUL 使用jul-to-slf4j.jar Spring是用JCL作为日志门面的,那我们的应用是slf4j + logback,怎么让Spring也用到logback作为日志输出呢?
也是依赖了JCL。 ,确实更加优雅,但是由于之前很多代码库已经使用JCL,虽然出现slf4j和JCL之间的桥接转换,但是集成的时候问题依然多多,对很多新手来说确实会很懊恼,因为比单独的log4j时代“复杂”多了,抱怨声确实很多 为了使使用JCL等等其他日志系统后者实现的用户可以很简单地切换到slf4j上来,给出了各种桥接工程,比如:jcl-over-slf4j会把对JCL的调用都桥接到slf4j上来,可以看出jcl-over-slf4j 的api和JCL是相同的,所以这两个jar是不能共存的。 JCL(commons-logging) 由于项目的日志打印必然选择两个框架中至少一个,这时候,Apache的JCL(commons-logging)诞生了。
(表示指定jcl) • log4j-slf4j-impl(表示指定log4j2) • logback-classic(表示指定logback) 门面模式 JCL 和slf4j 都使用了一种外观模式( 也是依赖了JCL。 ,确实更加优雅,但是由于之前很多代码库已经使用JCL,虽然出现slf4j和JCL之间的桥接转换,但是集成的时候问题依然多多,对很多新手来说确实会很懊恼,因为比单独的log4j时代“复杂”多了,可以关注下这个 为了使使用JCL等等其他日志系统后者实现的用户可以很简单地切换到slf4j上来,给出了各种桥接工程,比如:jcl-over-slf4j会把对JCL的调用都桥接到slf4j上来,可以看出jcl-over-slf4j 的api和JCL是相同的,所以这两个jar是不能共存的。
Apache见此,开发了JCL(Jakarta Commons Logging),即commons-logging-xx.jar。它只提供一套通用的日志接口api,并不提供日志的实现。 这样看上去也挺美好的,但是log4j的作者觉得JCL不好用,自己开发出slf4j,它跟JCL类似,本身不替供日志具体实现,只对外提供接口或门面。目的就是为了替代JCL。 JCL commons-logging已经停止更新,最后的状态如下所示: JCL支持日志组件不多,不过也有很人用的,例如Spring 现在用的也越来越少了,也不多讲了 SLF4J 因为当时Java的日志组件比较混乱繁杂 图来源于官方文档 其实总的来说,无论就是以下几种情况 你在用JCL 使用jcl-over-slf4j.jar适配 你在用log4j 使用log4j-over-slf4j.jar适配 你在用JUL 使用 Spring是用JCL作为日志门面的,那我们的应用是slf4j + logback,怎么让Spring也用到logback作为日志输出呢?
Apache见此,开发了JCL(Jakarta Commons Logging),即commons-logging-xx.jar。它只提供一套通用的日志接口api,并不提供日志的实现。 这样看上去也挺美好的,但是log4j的作者觉得JCL不好用,自己开发出slf4j,它跟JCL类似,本身不替供日志具体实现,只对外提供接口或门面。目的就是为了替代JCL。 JCL commons-logging已经停止更新,最后的状态如下所示: JCL支持日志组件不多,不过也有很人用的,例如Spring 现在用的也越来越少了,也不多讲了 SLF4J 因为当时Java的日志组件比较混乱繁杂 图来源于官方文档(https://www.slf4j.org/legacy.html) 其实总的来说,无论就是以下几种情况 你在用JCL 使用jcl-over-slf4j.jar适配 你在用log4j Spring是用JCL作为日志门面的,那我们的应用是slf4j + logback,怎么让Spring也用到logback作为日志输出呢?
Apache见此,开发了JCL(Jakarta Commons Logging),即commons-logging-xx.jar。它只提供一套通用的日志接口api,并不提供日志的实现。 这样看上去也挺美好的,但是log4j的作者觉得JCL不好用,自己开发出slf4j,它跟JCL类似,本身不替供日志具体实现,只对外提供接口或门面。目的就是为了替代JCL。 JCL commons-logging已经停止更新,最后的状态如下所示: JCL支持日志组件不多,不过也有很人用的,例如Spring 现在用的也越来越少了,也不多讲了 SLF4J 因为当时Java的日志组件比较混乱繁杂 图来源于官方文档 upload successful 其实总的来说,无论就是以下几种情况 你在用JCL 使用jcl-over-slf4j.jar适配 你在用log4j 使用log4j-over-slf4j.jar Spring是用JCL作为日志门面的,那我们的应用是slf4j + logback,怎么让Spring也用到logback作为日志输出呢?