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 类加载器如何替代它?这里不应该是个例外吗?

4

2 回答 2

4

If you extract the actual slf4j-api jar you'll notice that org.slf4j.impl.StaticLoggerBinder is not actually included in the jar. SFL4J api is compiled against the class at build but it isn't actually included in the artifact. If you look at the source for org.slf4j.impl.StaticLoggerBinder in the api module it has no implementation, all the public instance methods throw UnsupportedOperationException. This is ok, again because that class is excluded from the slf4j-api jar.

The classloader behaves normally and select the first version of org.slf4j.impl.StaticLoggerBinder that is found when the class needs to be loaded. This will generally be from the first slf4j implementation jar that it listed on the classpath.

Note: The findPossibleStaticLoggerBinderPathSet() is only used to warn that there are multiple bindings present on the classpath. It does not actually load any bindings.

于 2012-09-01T05:28:15.420 回答
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仅用于记录目的是可以理解的。

于 2012-08-31T23:03:20.097 回答