zoukankan      html  css  js  c++  java
  • Spring5.2.x02日志体系

    现象

    1. Spring体系中, 如果log是由spring-jcl搞出来的, 那么log4j的配置会覆盖logback;即使有logback与slf4j的绑定器, 也会优先使用log4j; 而其他, 如mybatis里的日志, 还是用自己的独立的log组件来打印
    2. Spring-boot 默认使用logback, 日志技术是统一的, 所有的是用一致的log组件

    问题

    1. Spring的日志体系为什么与mybatis不互通
    2. Spring-boot为什么可以让日志技术统一

    java日志分类

    实现类框架

    1. JUL: java自带log框架
    2. Log4j/Log4j2/LogBack: 第三方日志记录框架

    门面框架

    1. JCL: 面向Log接口编程, 缺点是不更新、无法解决历史硬编码的log、log组件的选择范围是硬编码于代码中
    2. Slf4j: 通过 Adapter 和 Bridge, 解决了历史硬编码的log不统一; 通过绑定器, 解决log组件的范围自行配置

    Spring-JCL

    spring4.x用的是apache的jcl, 5.x之后用的是自己module的spring-jcl, 因为原来的jcl没有继续维护, spring-jcl自行维护了

    spring-jcl只要看到log4j2, 就会启用, 详见以下代码片段

    	private static final String LOG4J_SPI = "org.apache.logging.log4j.spi.ExtendedLogger";
    
    	private static final String LOG4J_SLF4J_PROVIDER = "org.apache.logging.slf4j.SLF4JProvider";
    
    	private static final String SLF4J_SPI = "org.slf4j.spi.LocationAwareLogger";
    
    	private static final String SLF4J_API = "org.slf4j.Logger";
    		// 只要有 log4j
    		if (isPresent(LOG4J_SPI)) {
    			// 有桥接器 && 有slf4j, 才启用 slf4j
    			if (isPresent(LOG4J_SLF4J_PROVIDER) && isPresent(SLF4J_SPI)) {
    				// log4j-to-slf4j bridge -> we'll rather go with the SLF4J SPI;
    				// however, we still prefer Log4j over the plain SLF4J API since
    				// the latter does not have location awareness support.
    				logApi = LogApi.SLF4J_LAL;
    			}
    			else {
    				// Use Log4j 2.x directly, including location awareness support
    				logApi = LogApi.LOG4J;
    			}
    		}
    		else if (isPresent(SLF4J_SPI)) {
    			// Full SLF4J SPI including location awareness support
    			logApi = LogApi.SLF4J_LAL;
    		}
    		else if (isPresent(SLF4J_API)) {
    			// Minimal SLF4J API without location awareness support
    			logApi = LogApi.SLF4J;
    		}
    		else {
    			// java.util.logging as default
    			logApi = LogApi.JUL;
    		}
    

    基本原理, 就是看能不能用反射找到对应的类, 找不到说明没有运行环境没有这个类, catch住为false即可

    导致spring内部的log和外部其他的log不一定统一, 可能会出现Spring里面是log4j2, Tomcat又是 jul, 不能统一配置

    因此要加一个log4j-to-slf4j的桥接器(Spring-boot-web默认配置了桥接器, 日志能统一为logback)

    从日志框架转向SLF4J 桥接器

    桥接器的包结构和需要桥接的日志框架是一样的, 类也是一样的, 这样编译就不会报错

    应该用了代理, 不知道细节是怎么实现的...

    1. jul-to-slf4j:jdk-logging到slf4j的桥梁
    2. log4j-over-slf4j:log4j1到slf4j的桥梁
    3. jcl-over-slf4j:commons-logging到slf4j的桥梁

    从SLF4J转向具体的日志框架 绑定器

    1. slf4j-jdk14:slf4j到jdk-logging的桥梁
    2. slf4j-log4j12:slf4j到log4j1的桥梁
    3. log4j-slf4j-impl:slf4j到log4j2的桥梁
    4. logback-classic:slf4j到logback的桥梁
    5. slf4j-jcl:slf4j到commons-logging的桥梁
  • 相关阅读:
    Java实现 LeetCode 136 只出现一次的数字
    Java实现 LeetCode 136 只出现一次的数字
    Java实现 LeetCode 136 只出现一次的数字
    Java实现 LeetCode 135 分发糖果
    Java实现 LeetCode 135 分发糖果
    Java实现 LeetCode 135 分发糖果
    Java实现 LeetCode 134 加油站
    Java实现 LeetCode 134 加油站
    Java实现 LeetCode 134 加油站
    Java实现 LeetCode 133 克隆图
  • 原文地址:https://www.cnblogs.com/richardhaha/p/15773452.html
Copyright © 2011-2022 走看看