SLF4J的全称是 Simple Logging Facade for Java(简单java日志门面)
SLF4J自己不提供具体的日志功能实现,只是提供了一个统一的日志门面,在这个统一的门面之下,用户可以选择他们喜欢的日志的具体实现。
考虑下面一个场景:我们对外提供的工具包使用了log4j来管理日志,另外一个团队如果使用logback来管理他们的日志,在引入我们提供的工具包之后他们的项目中就会有两个不同的日志管理API,使用SLF4J可以解决这个问题。我们可以使用SLF4J + log4j来开发我们的工具包,客户端在使用我们的API的时候可以不用引入log4j的包
我们在使用SLF4J的时候通常使用下面的方式来得到Logger
Logger logger = LoggerFactory.getLogger(ClassName); //Logger 和LoggerFactory都是 slf4j-api.jar中 org.slf4j包下边的类
下边是getLogger的定义:
public static Logger getLogger(String name) { ILoggerFactory iLoggerFactory = getILoggerFactory(); return iLoggerFactory.getLogger(name); }
getILoggerFactory()方法最终调用的是 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); replayEvents(); } 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); } }
findPossibleStaticLoggerBinderPathSet()方法会在calsspath中寻找名为org.slf4j.impl.StaticLoggerBinder的类来确定项目中有哪些具体的日志实现
针对log4j来说,我们如果要使用SLF4J + log4j 来管理我们的日志,则需要三个相关的jar包(slf4j-api.jar、slf4j-log4j12.jar、log4j.jar)。slf4j-api.jar中有Logger、LoggerFactory等相应的类,slf4j-log4j12.jar中有org.slf4j.impl.StaticLoggerBinder 以及相应的 Log4jLoggerFactory 和能将log4j的Logger转换为slf4j的Logger的Log4jLoggerAdapter(下图是slf4j-log4j.jar中包含的类,一共6个:)
org.slf4j.impl.StaticLoggerBinder 类中绑定了Log4jLoggerFactory,在Log4jLoggerFactory的getLogger(String name)方法中使用 Log4jLoggerAdapter来实现了对log4j的注入:
public Logger getLogger(String name) { Logger slf4jLogger = loggerMap.get(name); if (slf4jLogger != null) { return slf4jLogger; } else { org.apache.log4j.Logger log4jLogger; if (name.equalsIgnoreCase(Logger.ROOT_LOGGER_NAME)) log4jLogger = LogManager.getRootLogger(); else log4jLogger = LogManager.getLogger(name); Logger newInstance = new Log4jLoggerAdapter(log4jLogger); Logger oldInstance = loggerMap.putIfAbsent(name, newInstance); return oldInstance == null ? newInstance : oldInstance; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现