slf4j如何将sfl4j-api中放置的org.slf4j.impl.StaticLoggerBinder替换为真正的StaticLoggerBinder

问题描述 投票:0回答:3

slf4j api 中存在 org.slf4j.impl.StaticLoggerBinder、org.slf4j.impl.StaticMarkerBinder、org.slf4j.impl.StaticMDCBinder 类。但是到具体记录器的每个绑定都应该包含相同的类。

例如:

http://grepcode.com/file/repo1.maven.org/maven2/org.slf4j/slf4j-api/1.6.1/org/slf4j/impl/StaticLoggerBinder.java?av=f

及其 log4j 实现: http://grepcode.com/file/repo1.maven.org/maven2/org.slf4j/slf4j-log4j12/1.6.1/org/slf4j/impl/StaticLoggerBinder.java?av=f

java类加载器如何替代它?这里不应该是一个例外吗?

java classloader slf4j
3个回答
5
投票

如果您提取实际的 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()
仅用于警告类路径上存在多个绑定。它实际上并不加载任何绑定。


1
投票

嗯,好问题,因为

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
仅用于记录目的。


0
投票

所以呢? Slf4j不使用Java SPI加载Logback服务吗?

© www.soinside.com 2019 - 2024. All rights reserved.