关于slf4j:SLF4J门面日志框架源码探索-京东云技术团队
1 SLF4J介绍SLF4J即Simple Logging Facade for Java,它提供了Java中所有日志框架的简略外观或形象。因而,它使用户可能应用单个依赖项解决任何日志框架,例如:Log4j,Logback和JUL(java.util.logging)。通过在类门路中插入适当的 jar 文件(绑定),能够在部署时插入所需的日志框架。如果要更换日志框架,仅仅替换依赖的slf4j bindings。比方,从java.util.logging替换为log4j,仅仅须要用slf4j-log4j12-1.7.28.jar替换slf4j-jdk14-1.7.28.jar。 2 SLF4J源码剖析咱们通过代码动手,层层加码,直观感触SLF4J打印日志,并跟踪代码寻根究底。次要理解,SLF4J是如何作为门面和其余日志框架进行解耦。 2.1 pom只援用依赖slf4j-api,版本是1.7.30 <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.30</version> </dependency>2.1.1 执行一个Demopublic class HelloSlf4j { public static void main(String[] args) { Logger logger = LoggerFactory.getLogger(HelloSlf4j.class); logger.info("Hello World info"); }}2.1.2 日志提示信息绑定org.slf4j.impl.StaticLoggerBinder失败。如果在类门路上没有找到绑定,那么 SLF4J 将默认为无操作实现 []() 2.1.3 跟踪源码点开办法getLogger(),能够直观看到LoggerFactory应用动态工厂创立Logger。通过以下办法,逐渐点击,报错也很容易找到,能够在bind()办法看到打印的异样日志信息。 org.slf4j.LoggerFactory#getLogger(java.lang.Class<?>) org.slf4j.LoggerFactory#getLogger(java.lang.String) org.slf4j.LoggerFactory#getILoggerFactory org.slf4j.LoggerFactory#performInitialization org.slf4j.LoggerFactory#bind private final static void bind() { try { Set<URL> 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); } 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); } finally { postBindCleanUp(); } }进一步剖析绑定办法findPossibleStaticLoggerBinderPathSet(),能够发现在以后ClassPath下查问了所有该门路的资源“org/slf4j/impl/StaticLoggerBinder.class”,这里可能没有加载到任何文件,也可能绑定多个,对没有绑定和绑定多个的场景进行了敌对提醒。这里通过门路加载资源的目标次要用来对加载的各种异样场景提醒。 ...