SLF4J-API类加载如何优先于虚拟绑定?

时间:2013-07-17 17:18:06

标签: java classloader slf4j

如果你看一下slf4j-api的源代码(任何现代版本,比如1.7.5),就会有一个LoggerFactory类,其中包含以下方法:

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;
}

当您调用任何Logger方法(调试,信息,警告,错误等)并且SLF4J绑定尚未初始化 时,会调用此方法。这就是SLF4J如何确定在运行时使用哪种绑定。

基本上,为SLF4J编写正确绑定的一种方法是实现自己的org.slf4j.impl.StaticLoggerBinder类。但是,slf4j-api JAR还附带了它自己的伪org.slf4j.impl.StaticLoggerBinder实现,可能是为了防止SLF4J开发期间的编译器错误(或者如果没有提供这样的StaticLoggerBinder则作为无操作回退通过约束)。

因此,如果您的运行时类路径中有slf4j-api-1.7.5slf4j-simple-1.7.5,那么您第一次使用时,例如Logger#info(String),就会定义StaticLoggerBinder slf4j-simple JAR将被选中 over StaticLoggerBinder JAR中定义的slf4j-api

我试图了解这种“偏好”/优先级(绑定impl over api impl)是如何工作的。上述方法如何首先选择绑定的StaticLoggerBinder而非假人StaticLoggerBinder中提供了slf4j-api

提前致谢!

1 个答案:

答案 0 :(得分:2)

虚拟StaticLoggerBinder根本不包含在slf4j-api jar文件中。

请参阅slf4j-api源代码here中的pom.xml。虚拟活页夹被删除。