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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | // 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 实现;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)