slf4j如何绑定到实现?在编译期间它真的这样做了吗?

Eri*_*rik 11 slf4j

在slf4j的文档中,它说绑定发生在complie时间:

"SLF4J不依赖于任何特殊的类加载器机器.实际上,每个SLF4J绑定在编译时都是硬连线使用一个且只有一个特定的日志框架.例如,slf4j-log4j12-1.7.5.jar绑定绑定在编译时使用log4j.在您的代码中,除了slf4j-api-1.7.5.jar之外,您只需将您选择的一个且只有一个绑定放到相应的类路径位置.不要在您的代码上放置多个绑定类路径.这是一般概念的图解说明." http://www.slf4j.org/manual.html

这是如何运作的?

Rad*_*Rad 6

这也是我的问题,我想添加我的答案,因为发现其他两个答案不够清楚(尽管完全正确)。

LoggerFactory.bind()首先,检查in的实现中的这一行slf4j-api链接

// the next line does the binding
StaticLoggerBinder.getSingleton();
Run Code Online (Sandbox Code Playgroud)

有一个类叫做org.slf4j.impl.StaticLoggerBinder. 在github上检查其实现。

现在继续从中央 Maven 存储库下载slf4j-api.jar,解压并查找StaticLoggerBinder.class文件。

不要尝试!你不能。事实上,整个产品org.slf4j.impl已从包装中取出。检查pom.xml项目的情况:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-antrun-plugin</artifactId>
    <executions>
      <execution>
        <phase>process-classes</phase>
        <goals>
         <goal>run</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
      <tasks>
        <echo>Removing slf4j-api's dummy StaticLoggerBinder and StaticMarkerBinder</echo>
        <delete dir="target/classes/org/slf4j/impl"/>
      </tasks>
    </configuration>
  </plugin>
Run Code Online (Sandbox Code Playgroud)

最后,检查 SLF4j 的绑定包之一,例如slf4j-simple。能找到org.slf4j.impl.StaticLoggerBinder课吗?

总之,当slf4j-api.jar您的运行时环境中只有一个(且只有一个)绑定包时,您就只有一个org.slf4j.impl.StaticLoggerBinder执行绑定的类。


Dai*_*ian 5

这是slf4j的源代码.Slf4j将在类路径中找到路径为" org/slf4j/impl/StaticLoggerBinder.class "的所有类.如果有多个,jvm将只随机选取一个.有关详细信息,请参阅此处:http://www.slf4j.org/codes.html#multiple_bindings

// We need to use the name of the StaticLoggerBinder class, but we can't
// reference
// the class itself.

private static String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class";

static Set<URL> findPossibleStaticLoggerBinderPathSet() {
 // use Set instead of list in order to deal with bug #138
 // LinkedHashSet appropriate here because it preserves insertion order
 // during iteration
    Set<URL> staticLoggerBinderPathSet = new LinkedHashSet<URL>(); 
    try {
        ClassLoader loggerFactoryClassLoader = LoggerFactory.class.getClassLoader();
        Enumeration<URL> paths;
        if (loggerFactoryClassLoader == null) {
            paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);
        } else {
            paths = loggerFactoryClassLoader.getResources(STATIC_LOGGER_BINDER_PATH);
        }
        while (paths.hasMoreElements()) {
            URL path = paths.nextElement();
            staticLoggerBinderPathSet.add(path);
        }
    } catch (IOException ioe) {
        Util.report("Error getting resources from path", ioe);
    }
    return staticLoggerBinderPathSet;
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*ton 4

据我所知,它通过期望类 StaticLoggingBinder 位于同一个包(org.slf4j.impl)中来实现这一点,而不管实现如何 - 所以它总是在同一个地方找到它。

  • 那么如果我在同一个包(org.slf4j.impl)中有多个 StaticLoggingBinder 怎么办?例如,我在同一个项目中有 slf4j-log4j12.jar 和 logback-classic.jar,哪个将被绑定? (2认同)