博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
日志框架学习2
阅读量:4124 次
发布时间:2019-05-25

本文共 7085 字,大约阅读时间需要 23 分钟。

1.slf4j 源码分析

import org.slf4j.Logger;import org.slf4j.LoggerFactory;private Logger log = LoggerFactory.getLogger(this.getClass());

1.1 getLogger方法解析

public static Logger getLogger(Class
clazz) { Logger logger = getLogger(clazz.getName()); if (DETECT_LOGGER_NAME_MISMATCH) { Class
autoComputedCallingClass = Util.getCallingClass(); if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) { Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(), autoComputedCallingClass.getName())); Util.report("See " + LOGGER_NAME_MISMATCH_URL + " for an explanation"); } } return logger; }

后半段逻辑 :当传进来的clazz和调用方的class名字不一致时是否打印警告信息(默认不打印)、

1.2getLogger方法的具体实现:

public static Logger getLogger(String name) {    ILoggerFactory iLoggerFactory = getILoggerFactory();    return iLoggerFactory.getLogger(name);}

通过getILoggerFactory获取对应的工厂实现类,继而获取对应的log对象

1.3getILoggerFactory方法详解

public static ILoggerFactory getILoggerFactory() {        if (INITIALIZATION_STATE == UNINITIALIZED) {            synchronized (LoggerFactory.class) {                if (INITIALIZATION_STATE == UNINITIALIZED) {                    INITIALIZATION_STATE = ONGOING_INITIALIZATION;                    performInitialization();                }            }        }        switch (INITIALIZATION_STATE) {        case SUCCESSFUL_INITIALIZATION:            return StaticLoggerBinder.getSingleton().getLoggerFactory();        case NOP_FALLBACK_INITIALIZATION:            return NOP_FALLBACK_FACTORY;        case FAILED_INITIALIZATION:            throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);        case ONGOING_INITIALIZATION:            // support re-entrant behavior.            // See also http://jira.qos.ch/browse/SLF4J-97            return SUBST_FACTORY;        }        throw new IllegalStateException("Unreachable code");    }

首次执行performInitialization进行初始化,根据INITIALIZATION_STATE的值进入不同操作(初始化成功即可返回对用的工厂类,继而获取对应log对象)

1.4performInitialization方法说明

private final static void performInitialization() {        bind();        if (INITIALIZATION_STATE == SUCCESSFUL_INITIALIZATION) {            versionSanityCheck();        }    }

bind为实际performInitialization的方法,versionSanityCheck只是进行了jdk版本校验,不再次详述

1.5bind

private final static void bind() {        try {            Set
staticLoggerBinderPathSet = null; // skip check under android, see also // http://jira.qos.ch/browse/SLF4J-328 if (!isAndroid()) { staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet(); reportMultipleBindingAmbiguity(staticLoggerBinderPathSet); } // the next line does the binding StaticLoggerBinder.getSingleton(); INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION; reportActualBinding(staticLoggerBinderPathSet); fixSubstituteLoggers(); replayEvents(); // release all resources in SUBST_FACTORY SUBST_FACTORY.clear(); } catch (NoClassDefFoundError ncde) { String msg = ncde.getMessage(); if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) { INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION; Util.report("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\"."); Util.report("Defaulting to no-operation (NOP) logger implementation"); Util.report("See " + NO_STATICLOGGERBINDER_URL + " for further details."); } else { failedBinding(ncde); throw ncde; } } catch (java.lang.NoSuchMethodError nsme) { String msg = nsme.getMessage(); if (msg != null && msg.contains("org.slf4j.impl.StaticLoggerBinder.getSingleton()")) { INITIALIZATION_STATE = FAILED_INITIALIZATION; Util.report("slf4j-api 1.6.x (or later) is incompatible with this binding."); Util.report("Your binding is version 1.5.5 or earlier."); Util.report("Upgrade your binding to version 1.6.x."); } throw nsme; } catch (Exception e) { failedBinding(e); throw new IllegalStateException("Unexpected initialization failure", e); } }

bind中关键方法

findPossibleStaticLoggerBinderPathSet();–寻找绑定路径
StaticLoggerBinder.getSingleton();–进行绑定获取工厂方法
fixSubstituteLoggers();–没明白是什么作用,有大佬看到望指点下
replayEvents();–没明白是什么作用,有大佬看到望指点下

1.5.1findPossibleStaticLoggerBinderPathSet

static Set
findPossibleStaticLoggerBinderPathSet() { // use Set instead of list in order to deal with bug #138 // LinkedHashSet appropriate here because it preserves insertion order // during iteration Set
staticLoggerBinderPathSet = new LinkedHashSet
(); try { ClassLoader loggerFactoryClassLoader = LoggerFactory.class.getClassLoader(); Enumeration
paths; if (loggerFactoryClassLoader == null) { paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH); } else { paths = loggerFactoryClassLoader.getResources(STATIC_LOGGER_BINDER_PATH); } while (paths.hasMoreElements()) { URL path = paths.nextElement(); staticLoggerBinderPathSet.add(path); } } catch (IOException ioe) { Util.report("Error getting resources from path", ioe); } return staticLoggerBinderPathSet; }

获取所有org/slf4j/impl/StaticLoggerBinder.class类的路径(获取大于1个时进行警告但仅仅是警告不影响运行)

详见官方文档说明:

The warning emitted by SLF4J is just that, a warning. Even when multiple bindings are present, SLF4J will pick one logging

framework/implementation and bind with it. The way SLF4J picks a
binding is determined by the JVM and for all practical purposes should
be considered random. As of version 1.6.6, SLF4J will name the
framework/implementation class it is actually bound to.
Embedded components such as libraries or frameworks should not declare a dependency on any SLF4J binding but only depend on
slf4j-api. When a library declares a compile-time dependency on a
SLF4J binding, it imposes that binding on the end-user, thus negating
SLF4J’s purpose. When you come across an embedded component declaring
a compile-time dependency on any SLF4J binding, please take the time
to contact the authors of said component/library and kindly ask them
to mend their ways.

1.5.2(slf4j关键)

StaticLoggerBinder类即使用所有findPossibleStaticLoggerBinderPathSet找到的路径中的一个类(具体根据jvm加载类的顺序,据本人实验所得该顺序即为引用jar的顺序,例如同时引入了slf4j-nop.jar slf4j-simple.jar, slf4j-log4j12.jar, slf4j-jdk14.jar , logback-classic.jar,会使用slf4j-nop.jar中的StaticLoggerBinder来获取对应的工厂类)
至于slf4j-api.源码中StaticLoggerBinder类其实在打出的jar包slf4j-api.jar中是不存在的因为他的pom文件中写了,在打包时会删除源码中impl的目录以及其下文件。

1.5.3 reportActualBinding

输出实际(绑定)使用的StaticLoggerBinder

转载地址:http://rwepi.baihongyu.com/

你可能感兴趣的文章
虚拟机 CentOS7/RedHat7/OracleLinux7 配置静态IP地址 Ping 物理机和互联网
查看>>
Jackson Tree Model Example
查看>>
常用js收集
查看>>
如何防止sql注入
查看>>
maven多工程构建与打包
查看>>
springmvc传值
查看>>
Java 集合学习一 HashSet
查看>>
在Eclipse中查看Android源码
查看>>
Android使用webservice客户端实例
查看>>
层在页面中的定位
查看>>
[转]C语言printf
查看>>
C 语言 学习---获取文本框内容及字符串拼接
查看>>
C 语言学习 --设置文本框内容及进制转换
查看>>
C 语言 学习---判断文本框取得的数是否是整数
查看>>
C 语言 学习---ComboBox相关、简单计算器
查看>>
C 语言 学习---ComboBox相关、简易“假”管理系统
查看>>
C 语言 学习---回调、时间定时更新程序
查看>>
C 语言 学习---复选框及列表框的使用
查看>>
第四章 - 程序计数器
查看>>
第七章 - 本地方法栈
查看>>