slf4j api 中存在 org.slf4j.impl.StaticLoggerBinder、org.slf4j.impl.StaticMarkerBinder、org.slf4j.impl.StaticMDCBinder 类。但是到具体记录器的每个绑定都应该包含相同的类。
例如:
java类加载器如何替代它?这里不应该是一个例外吗?
如果您提取实际的 slf4j-api jar,您会发现
org.slf4j.impl.StaticLoggerBinder
实际上并未包含在 jar 中。 SFL4J api 在构建时针对类进行编译,但实际上并未包含在工件中。如果您查看 api 模块中 org.slf4j.impl.StaticLoggerBinder
的源代码,它没有实现,所有公共实例方法都会抛出 UnsupportedOperationException
。这也没关系,因为该类已从 slf4j-api jar 中排除。
类加载器表现正常,并选择需要加载类时找到的第一个版本
org.slf4j.impl.StaticLoggerBinder
。这通常来自类路径上列出的第一个 slf4j 实现 jar。
注意:
findPossibleStaticLoggerBinderPathSet()
仅用于警告类路径上存在多个绑定。它实际上并不加载任何绑定。
嗯,好问题,因为
slf4j
应该不使用运行时加载类。看起来在下面的方法中使用了启动时的类加载器检查:
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);
}
while (paths.hasMoreElements()) {
URL path = (URL) paths.nextElement();
staticLoggerBinderPathSet.add(path);
}
} catch (IOException ioe) {
Util.report("Error getting resources from path", ioe);
}
return staticLoggerBinderPathSet;
}
@Dev 是对的 -
org.slf4j.impl.StaticLoggerBinder
仅包含在 slf4j-api 源代码中,而不是二进制文件中 - 由于编译原因,仅包含在源代码中是简单的技巧。可以理解的是,findPossibleStaticLoggerBinderPathSet
仅用于记录目的。
所以呢? Slf4j不使用Java SPI加载Logback服务吗?