LogFacade---SLF4J
概述
Simple Logging Facade for Java(SLF4J);
用作各种日志框架(eg:java.util.logging,logback,log4j)的简单外观或抽象,允许最终用户在部署 时插入所需的日志记录框架;
不提供完整的日志记录解决方案;
使用SLF4J无法执行配置appender或设置日志记录级别等操作。
因此,在某个时间点,任何非平凡的应用程序都需要直接调用底层日志记录系统;
因此一般情况下slf4j都会和log4j,logback等日志框架一起使用;
slf4j是一个日志标准,同时日志框架都会实现这个标准,因此使用slf4j可以极大的降低维护成本;
SPI机制
slf4j 提供的 service LoggerFactory ,在Classpath下查找 org/slf4j/impl/StaticLoggerBinder.class
链路
LoggerFactory.getLogger
// org.slf4j.LoggerFactory.getLogger(java.lang.Class) // Return a logger named corresponding to the class passed as parameter, using the statically bound {@link ILoggerFactory} instance. public static Logger getLogger(Class clazz) { return getLogger(clazz.getName()); } // org.slf4j.LoggerFactory.getLogger(java.lang.String) // Return a logger named according to the name parameter using the statically bound {@link ILoggerFactory} instance. public static Logger getLogger(String name) { ILoggerFactory iLoggerFactory = getILoggerFactory(); return iLoggerFactory.getLogger(name); } // org.slf4j.LoggerFactory.getILoggerFactory // Return the {@link ILoggerFactory} instance in use.ILoggerFactory instance is bound with this class at compile time. public static ILoggerFactory getILoggerFactory() { 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://bugzilla.slf4j.org/show_bug.cgi?id=106 return TEMP_FACTORY; } throw new IllegalStateException("Unreachable code"); } // org.slf4j.LoggerFactory.performInitialization private final static void performInitialization() { bind(); if (INITIALIZATION_STATE == SUCCESSFUL_INITIALIZATION) { versionSanityCheck(); } } // org.slf4j.LoggerFactory.bind private final static void bind() { try { Set staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet(); // 获取classpath下的org/slf4j/impl/StaticLoggerBinder.class reportMultipleBindingAmbiguity(staticLoggerBinderPathSet); // the next line does the binding StaticLoggerBinder.getSingleton(); // INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION; reportActualBinding(staticLoggerBinderPathSet); emitSubstituteLoggerWarning(); } 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.indexOf("org.slf4j.impl.StaticLoggerBinder.getSingleton()") != -1) { 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); } } // org.slf4j.LoggerFactory.findPossibleStaticLoggerBinderPathSet // We need to use the name of the StaticLoggerBinder class, but we can't reference the class itself. private 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); // 获取classpath下的org/slf4j/impl/StaticLoggerBinder.class } while (paths.hasMoreElements()) { URL path = (URL) paths.nextElement(); staticLoggerBinderPathSet.add(path); } } catch (IOException ioe) { Util.report("Error getting resources from path", ioe); } return staticLoggerBinderPathSet; } // org.slf4j.impl.StaticLoggerBinder.getSingleton public static StaticLoggerBinder getSingleton() { return SINGLETON; } // ch.qos.logback.classic.LoggerContext.getLogger(java.lang.String) public final Logger getLogger(final String name) { //... Logger childLogger = (Logger) loggerCache.get(name); // 从缓存中取对应name的Logger //... loggerCache.put(childName, childLogger); }
log.debug
由具体的 log 实现;