How is slf4j attached to an implementation? Does this really happen at compile time?

The documentation for slf4j says that binding occurs at runtime:

"SLF4J does not rely on any special classloader equipment. In fact, each SLF4J binding is tightly bound at compile time to use one and only one specific logging structure. For example, the slf4j-log4j12-1.7.5.jar binding is bound at the time compilation to use log4j. In your code, in addition to slf4j-api-1.7.5.jar, you just drop one and only one binding of your choice in the appropriate location on the class path. Do not put more than one binding on your class path. Here graphic illustration of the general ideas. " http://www.slf4j.org/manual.html

How it works?

+11
slf4j
source share
6 answers

Here is the source code for slf4j. Slf4j will find the entire class in the classpath, whose path is " org / slf4j / impl / StaticLoggerBinder.class ". And if there are several, jvm will select only one at random. You can see more detailed information 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; } 
+5
source share

This was my question, and I would like to add my answer, since I found that the other two answers are not clear enough (although they are completely 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 out its implementation on github .

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

Do not try! You can not. In fact, all org.slf4j.impl been removed from the package. Check project 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 dummy StaticLoggerBinder and StaticMarkerBinder</echo> <delete dir="target/classes/org/slf4j/impl"/> </tasks> </configuration> </plugin> 

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

In sum, when you have slf4j-api.jar next to one (and only one) binding packages in your runtime, you only have one org.slf4j.impl.StaticLoggerBinder class that performs the binding.

+4
source share

From what I saw, he does this, expecting that the StaticLoggingBinder class will be in one package (org.slf4j.impl), regardless of implementation, so it always finds it in the same place.

+3
source share

Technically, at compile time there is no magic โ€œbindingโ€. โ€œBindingโ€ happened when SLF4J developers created libraries to handle the most popular Java registration frameworks.

When the docs say "binding is tightly bound at compile time," this means that SLF4J developers created a target library for a specific Java logging framework. SLF4J has libraries for Java Logging, Jakarta Commons Logging, Log4J, and console output. You will only need to enable one of these libraries at run time so that SLF4J can successfully create log messages.

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

0
source share

This is the same as @Rad said.

What I want to replenish is that if there are several StaticLoggerBinder tools in your StaticLoggerBinder , slf4j selects one of them RANDOMLY , as stated in multiple bindings :

The way SLF4J selects the binding is determined by the JVM and should be considered random for all practical purposes. Starting with version 1.6.6, SLF4J will name the framework / implementation class with which it is actually associated.

One more attention: if you plan to use your project as a library for other projects, you should include only slf4j-api , any implementation for slf4j-api not allowed:

Embedded components, such as libraries or platforms, should not declare dependency on any SLF4J binding, but depend only on slf4j-api. When a library declares a compile-time dependency on an SLF4J binding, it imposes that binding on the end user, thereby denying the purpose of SLF4J.

0
source share

The implementation is not bound at compile time (this is not static / early binding) or, in other words, an implementation that is not known at compile time .

In fact, it is the other way around where the implementation is bound at runtime , which means that the implementation is detected through dynamic / dynamic binding . The people from Slf4j actually announced how binding is done in their guide https://www.slf4j.org/manual.html :

SLF4J allows the end user to plug in the desired logging structure during deployment.

0
source share

All Articles