How does slf4j bind to implementation? Does it really do so during compile time?

后端 未结 6 1699
轮回少年
轮回少年 2021-02-13 03:58

In the documentation for slf4j it says that the binding happens during complie time:

\"SLF4J does not rely on any special class loader machinery. In fact, each SLF4J bi

相关标签:
6条回答
  • 2021-02-13 04:10

    Technically, there's no magic "binding" happening at compile time. The "binding" happened when the SLF4J developers created libraries to handle the most popular Java logging frameworks.

    When the docs say that the "binding is hardwired at compile time," it means the SLF4J developers have created a targeted library for a particular Java logging framework. SLF4J has libraries dedicated to Java Logging, Jakarta Commons Logging, Log4J, and console output. You will need to include only one of these libraries at runtime in order for SLF4J to successfully create log messages.

    For more information on how SLF4J works: A more visual way to understand SLF4J.

    0 讨论(0)
  • 2021-02-13 04:10

    It's just as @Rad said.

    What I wanna replenish is that if you have multiple StaticLoggerBinder implements in your runtime environment, slf4j choose one of them RANDOMLY, as said in multiple_bindings:

    The way SLF4J picks a binding is determined by the JVM and for all practical purposes should be considered random. As of version 1.6.6, SLF4J will name the framework/implementation class it is actually bound to.

    Another attention is that if your project is planned to be a library for other projects, only slf4j-api should be included, any implementation for slf4j-api is not allowed:

    Embedded components such as libraries or frameworks should not declare a dependency on any SLF4J binding but only depend on slf4j-api. When a library declares a compile-time dependency on a SLF4J binding, it imposes that binding on the end-user, thus negating SLF4J's purpose.

    0 讨论(0)
  • 2021-02-13 04:21

    Here is the source code of slf4j. Slf4j will find all the class in the class path whose path is "org/slf4j/impl/StaticLoggerBinder.class". And if there are more than one, jvm will pick up only one randomly.For more detail you can see here: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;
    }
    
    0 讨论(0)
  • 2021-02-13 04:22

    The implementation is not bound at compile-time (it's not a static/early binding) or in other words the implementation it's not known at compile time.

    Actually it's the vice-versa where the implementation is bound at runtime, meaning that the implementation is discovered through dynamic/runtime binding . The Slf4j folks have actually declared how the binding happens in their manual https://www.slf4j.org/manual.html:

    SLF4J allows the end-user to plug in the desired logging framework at deployment time.

    0 讨论(0)
  • 2021-02-13 04:24

    From what I have seen, it does this by expecting the class StaticLoggingBinder to be in the same package (org.slf4j.impl), regardless of the implementation - so it always finds it in the same place.

    0 讨论(0)
  • 2021-02-13 04:25

    It was my question too and I'd like to add my answer, since found the other two answer not clear enough (though are perfectly correct).

    First, check this line in the implementation of LoggerFactory.bind() in slf4j-api (link)

    // the next line does the binding
    StaticLoggerBinder.getSingleton();
    

    There is a class called org.slf4j.impl.StaticLoggerBinder. Check its implementation on github.

    Now go ahead and download the slf4j-api.jar from the central maven repository, extract it and find StaticLoggerBinder.class file.

    Don't try! You can't. In fact the whole org.slf4j.impl has been removed from the package. Check the pom.xml of the project:

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

    Last, check one of the SLF4j's binding packages, for example slf4j-simple. Can you find org.slf4j.impl.StaticLoggerBinder class?

    In sum, when you have slf4j-api.jar alongside one (and only one) of the binding packages in you runtime environment, you have only one org.slf4j.impl.StaticLoggerBinder class which does the binding.

    0 讨论(0)
提交回复
热议问题