How to enter SLF4J bindings using Guice?

After a quick inspection, it seems that SLF4J and Guice (well, in fact, any DI scheme) are a kind of conflicting philosophy. SLF4J uses the approach "hey, we will not know until we work with which classes we will be bound, and this is normal." On the other hand, Guice seems to be saying, "Hey, we need to know at compile time exactly what classes we are bound to."

So I ask: is it possible to use the Guice / Spring / any DI interface to configure / insert SLF4J?

The kicker is that the Java ClassLoader is what the ClassLoader actually injects at run time with the correct Logger / LoggerFactory / etc. objects, so I cannot figure out how to inject these ClassLoaders so that they return the org.slf4j.impl.Logger that I want at runtime:

I ask because I like the advantage of SLF4J and logging with the API, but also the advantages of DI. Is there any way to make this work? Thanks in advance!

+4
source share
3 answers

I believe this is not possible (unless you are doing something extremely cumbersome, like a container that creates a child class loader for your application ... something like that)

The main idea of ​​SLF4j to have a replaceable implementation is to have a middleware lib that provides org.slf4j.impl.StaticLoggerBinder , and the SLF4J API will look for this class through the class loader. Therefore, if there is more than 1 binder in the classpath, there is no way to distinguish the org.slf4j.impl.StaticLoggerBinder that they provide. The DI Framework is not going to help with this, given that the Logging environment is initialized before the DI happens.

If the SLF4J does not change its design in the future, we will not be able to do much. And, I doubt that even the SLF4J is changing its design. Since we cannot tell the DI container that Logging initialization is what it all depends on. I believe that there are more reasons to make it almost impossible.

However, that I doubt whether this is really related to DI? Honestly, I don't see a problem with controlling which logging binding is used by putting the appropriate JAR in the classpath. If you want to control it at runtime, as programmatically, I think writing a small container to launch your application is the way to go. However, this is not related to DI.

+3
source

One fairly simple approach to this problem is to insert an instance of ILoggerFactory into the LoggerFactory using the setILoggerFactory() method. (As of October 2012, the setILoggerFactory() method does not exist.)

The static binding mechanism currently implemented by SLF4J does nothing but install ILoggerFactory . Will this approach work for you?

+1
source

For those who find it now: Sangria implements a "context-sensitive binder" that works very well for this; see sangria-slf4j and sangria-contextual .

From the author’s blog article, you can configure SLF4J with the name logger factory as easily as:

 public class YourModule extends AbstractModule { @Override protected void configure() { install(new SangriaSlf4jModule()); } } 

... and there are examples of how to use new providers for your own types.

+1
source

Source: https://habr.com/ru/post/1442224/


All Articles