日志体系(二) 认识spring 5.0.x中的spring-jcl jar包,任意替换默认日志框架jul为log4j

前言

  • 上篇博客:日志体系(一)JCL + JUL + LOG4J大概介绍了一下apache公司开源的jcl这么一款抽象的日志框架,我们可以借助它来随意更换框架中使用的日志框架。
  • 由于jcl的自我抛弃,不再进行维护了。但是框架总归是要记录日志的。所以对于spring 5.0.x框架而言,它自己提供了一个jcl框架spring-jcl。下面我们开始认识下它

一、spring 5.0.x版本spring-jcl

1.1 jar包结构

在这里插入图片描述

  • Log.java。此接口抽象了日志的一些行为,比如记录info级别的日志、warn级别的日志等等
    public interface Log {
    
    	boolean isFatalEnabled();
    
    	boolean isErrorEnabled();
    
    	boolean isWarnEnabled();
    
    	boolean isInfoEnabled();
    
    	boolean isDebugEnabled();
    
    	boolean isTraceEnabled();
    
    	void fatal(Object message);
    
    	void fatal(Object message, Throwable t);
    
        void error(Object message);
    
        void error(Object message, Throwable t);
    
    	void warn(Object message);
    
    	void warn(Object message, Throwable t);
    
        void info(Object message);
    
        void info(Object message, Throwable t);
    
    	void debug(Object message);
    
    	void debug(Object message, Throwable t);
    
        void trace(Object message);
    
        void trace(Object message, Throwable t);
    
    }
    
  • LogFactory.java 创建Log类型的日志实例的工厂,里面大致做的事情就是根据当前项目中存在哪些日志的依赖来决定初始化哪种日志. 初始化顺序如下:
        // Log4j 2.x API 
    	1. org.apache.logging.log4j.spi.ExtendedLogger
    	// SLF4J 1.7 API
    	2. org.slf4j.spi.LocationAwareLogger
    	//  Try SLF4J 1.7 API
    	3. org.slf4j.Logger
    	// Default jul
    	4. java.util.logging.Logger
    
  • NoOpLog.java是Log接口的一个实现类,在spring-jcl中只有里面的SimpleLog.java类使用了它,但是SimpleLog.java类被spring使用@Deprecated注解标识了,这代表着,spring不使用它了,于是我们直接忽略NoOpLog.java和SimpleLog.java类。所以整个spring-jcl中,我们唯一要看的就是一个类LogFactory.java

1.2 spring-jcl之LogFactory类

  • 本次我们不总结日志的具体打印原理,只总结spring-jcl是如何根据依赖的jar包来生产对应的log对象的。主要看LogFactory的两个地方:静态代码块和getLog方法
  • LogFactory.java静态代码块
    private static LogApi logApi = LogApi.JUL;
    
    static {
    	ClassLoader cl = LogFactory.class.getClassLoader();
    	try {
    		// Try Log4j 2.x API
    		cl.loadClass("org.apache.logging.log4j.spi.ExtendedLogger");
    		logApi = LogApi.LOG4J;
    	}
    	catch (ClassNotFoundException ex1) {
    		try {
    			// Try SLF4J 1.7 SPI
    			cl.loadClass("org.slf4j.spi.LocationAwareLogger");
    			logApi = LogApi.SLF4J_LAL;
    		}
    		catch (ClassNotFoundException ex2) {
    			try {
    				// Try SLF4J 1.7 API
    				cl.loadClass("org.slf4j.Logger");
    				logApi = LogApi.SLF4J;
    			}
    			catch (ClassNotFoundException ex3) {
    				// Keep java.util.logging as default
    			}
    		}
    	}
    }
    
    由源码可知,spring-jcl加载日志的方式和apache开源出来的jcl加载日志的方式思想基本一致(这就是抽象的魅力)。spring-jcl LogFactory使用当前类的类加载器根据当前classpath中存在哪种jar包最终获取到对应的Class类赋值给logApi这个静态枚举对象(这个枚举可取: LOG4J, SLF4J_LAL, SLF4J, JUL四个值)。若在学习spring源码时,只引入了spring-context模块,那么此时logApi一定等于JUL。所以打印的是JUL的日志(上篇博客中特意提过,jul的日志的字体是红色的),如下图所示:(这要一定要注册一个bean进去,否则的话spring不会执行refresh方法,进而不会打印出日志!)
    在这里插入图片描述
    刚刚看了,spring-jcl的加载顺序为Log4j 2.xTry SLF4J 1.7 SPISLF4J 1.7 API。那我们现在按照源码中的提示添加Log4j 2.x试试

1.3 切换日志源为LOG4J

  • 因为在源码中有提示,需要加载的Log4j是2.x之后的版本,源码中有提供一个类:org.apache.logging.log4j.spi.ExtendedLogger。按照java包名的开发规范,这应该是apache开发的一个项目,于是我们去maven搜索下log4j, 找到2.12.1版本(主要要选择groupId为****),并添加依赖
    在这里插入图片描述
    maven添加依赖如下:
    	<dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.12.1</version>
        </dependency>
    
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.12.1</version>
        </dependency>
    
    于是我们启动项目,纳尼,日志不打印了, 反而打印了这么一句话:
    ERROR StatusLogger No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), or user programmatically provided configurations. Set system property 'log4j2.debug' to show Log4j 2 internal initialization logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2
    
    大致的意思就是需要一个配置文件。可以给jvm添加参数log4j2.debug来显示log4j 2.x内部初始化日志,可以按照如下图所示方式配置, 这里就不演示了。
    在这里插入图片描述
    我们言归正传,添加一个名叫log4j.xml的配置文件,并配置如下内容(这个配置的由来就是上面抛出异常指定的url, 只不过我做了修改,修改了打印日志的级别为dubug及以上):
    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="debug">
        <Appenders>
            <Console name="Console" target="SYSTEM_OUT">
                <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            </Console>
        </Appenders>
        <Loggers>
            <Root level="info">
                <AppenderRef ref="Console"/>
            </Root>
        </Loggers>
    </Configuration>
    
    最终的项目结构和运行结果如下:
    在这里插入图片描述,可能这个理由还不够足以证明打印日志的是log4j对象, 这样,我们查看打印spring日志的方法处打断点查看(在AbstractApplicationContext类的prepareRefresh方法下), 如下图:在这里插入图片描述
    综上所述,我们已经将spring5.0.x自带的jul日志切换成log4j了。切换其他的日志源也同理。

二、总结

  • 所有日志的对象都是从依赖的jar中生成的,所以关于日志的一些配置,比如支持打印的日志登记、打印的格式都是由对应的日志来决定的。比如上说的log4j日志,使用的就是自己的log4j.xml配置文件来指定要打印的日志级别
  • spring为了集成日志框架,自己开发了一个spring版本的jcl
  • I am a slow walker, but I never walk backwards
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
activation-1.1.1.jar activiti-bpmn-converter-5.21.0.jar activiti-bpmn-model-5.21.0.jar activiti-common-rest-5.21.0.jar activiti-crystalball-5.21.0.jar activiti-diagram-rest-5.21.0.jar activiti-engine-5.21.0.jar activiti-explorer-5.21.0.jar activiti-image-generator-5.21.0.jar activiti-json-converter-5.21.0.jar activiti-modeler-5.21.0.jar activiti-process-validation-5.21.0.jar activiti-spring-5.21.0.jar analyzer-2012_u6.jar aopalliance-1.0.jar apache-ant-zip-2.3.jar asm-4.2.jar aspectjrt-1.7.4.jar aspectjweaver-1.7.4.jar avalon-framework-api-4.3.1.jar avalon-framework-impl-4.3.1.jar batik-anim-1.7.jar batik-awt-util-1.7.jar batik-bridge-1.7.jar batik-codec-1.7.jar batik-css-1.7.jar batik-dom-1.7.jar batik-ext-1.7.jar batik-gvt-1.7.jar batik-js-1.7.jar batik-parser-1.7.jar batik-script-1.7.jar batik-svg-dom-1.7.jar batik-svggen-1.7.jar batik-transcoder-1.7.jar batik-util-1.7.jar batik-xml-1.7.jar cas-client-core-3.2.1.jar cglib-3.1.jar ckfinder-2.3.jar ckfinderplugin-fileeditor-2.3.jar ckfinderplugin-imageresize-2.3.jar classmate-1.1.0.jar commons-beanutils-1.9.1.jar commons-codec-1.9.jar commons-collections-3.2.1.jar commons-dbcp-1.4.jar commons-email-1.4.jar commons-fileupload-1.3.1.jar commons-io-2.4.jar commons-lang3-3.3.2.jar commons-logging-1.0.4.jar commons-pool-1.5.4.jar commons-pool2-2.0.jar core-2.2.jar dom4j-1.6.1.jar dozer-5.5.1.jar druid-1.0.18.jar ehcache-core-2.6.11.jar ehcache-web-2.0.4.jar fop-0.94.jar freemarker-2.3.20.jar groovy-all-2.4.5.jar guava-17.0.jar h2-1.3.176.jar hamcrest-core-1.3.jar hibernate-validator-5.2.4.Final.jar imgscalr-lib-4.2.jar jackson-annotations-2.2.3.jar jackson-core-2.2.3.jar jackson-databind-2.2.3.jar jackson-module-jaxb-annotations-2.2.3.jar javaGeom-0.11.1.jar javase-2.2.jar javax.mail-1.5.2.jar jboss-logging-3.2.1.Final.jar jcl-over-slf4j-1.7.7.jar jedis-2.5.1.jar joda-time-2.6.jar jstl-1.2.jar jtds-1.3.1.jar jul-to-slf4j-1.7.7.jar junit-4.11.jar log4j-1.2.17.jar mail-1.4.7.jar metadata-extractor-2.6.2.jar mybatis-3.2.8.jar mybatis-spring-1.2.3.jar mysql-connector-java-5.1.30.jar ojdbc14-10.2.0.4.0.jar poi-3.9.jar poi-ooxml-3.9.jar poi-ooxml-schemas-3.9.jar shiro-cas-1.2.3.jar shiro-core-1.2.3.jar shiro-ehcache-1.2.3.jar shiro-spring-1.2.3.jar shiro-web-1.2.3.jar sitemesh-2.4.2.jar slf4j-api-1.7.7.jar slf4j-log4j12-1.7.7.jar spring-aop-4.1.9.RELEASE.jar spring-beans-4.1.9.RELEASE.jar spring-context-4.1.9.RELEASE.jar spring-context-support-4.1.9.RELEASE.jar spring-core-4.1.9.RELEASE.jar spring-expression-4.1.9.RELEASE.jar spring-jdbc-4.1.9.RELEASE.jar spring-orm-4.1.9.RELEASE.jar spring-oxm-4.1.9.RELEASE.jar spring-security-config-3.2.3.RELEASE.jar spring-security-core-3.2.3.RELEASE.jar spring-security-crypto-3.2.3.RELEASE.jar spring-security-web-3.2.3.RELEASE.jar spring-test-4.1.9.RELEASE.jar spring-tx-4.1.9.RELEASE.jar spring-web-4.1.9.RELEASE.jar spring-webmvc-4.1.9.RELEASE.jar standard-1.1.2.jar stax-api-1.0.1.jar thumbnailator-0.4.2.jar UserAgentUtils-1.13.jar validation-api-1.1.0.Final.jar xercesImpl-2.8.1.jar xml-apis-1.3.04.jar xml-apis-ext-1.3.04.jar xmlbeans-2.3.0.jar xmlgraphics-commons-1.2.jar xmlpull-1.1.3.1.jar xmpcore-5.1.2.jar xpp3_min-1.1.4c.jar xstream-1.4.7.jar
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值