经过粗略的检查,似乎SLF4J和Guice(嗯,任何DI框架,真的)都是一种相互矛盾的哲学。 SLF4J采用的方式是“嘿,直到运行时我们才会知道我们要绑定哪些类,这没关系。”另一方面,Guice似乎说“嘿,我们需要在编译时确切知道我们绑定的类。“。
所以我问:是否可以使用Guice / Spring /任何DI框架来配置/注入SLF4J绑定?
Kicker是Java ClassLoader
在运行时使用正确的Logger / LoggerFactory /等真正“注入”SLF4J。对象,所以我无法弄清楚如何注入这些ClassLoaders,以便它们在运行时返回我想要的org.slf4j.impl.Logger
:
我问,因为我喜欢SLF4J的好处并且记录了API,但也喜欢DI的好处。有没有办法让这项工作?提前谢谢!
答案 0 :(得分:3)
我相信这是不可能的(除非你制作一些非常繁琐的东西,比如为你的app创建子类加载器的容器......就像那样)
SLF4j具有可替换实现的基本思想是让绑定器lib提供org.slf4j.impl.StaticLoggerBinder
,SLF4J API将通过类加载器查找此类。因此,如果类路径中有多个绑定器,则无法区分它们提供的org.slf4j.impl.StaticLoggerBinder
。鉴于Logging框架甚至在DI发生之前初始化,DI框架对此没有帮助。
除非SLF4J将来改变其设计,否则我们无能为力。并且,我怀疑即使SLF4J改变其设计也是可能的。因为我们无法告诉DI容器Logging初始化是每个人都依赖的东西。我相信有更多的理由使它几乎不可能实现。
然而,我怀疑的是,这真的与DI有关吗?老实说,我没有看到通过在类路径中放置相应的JAR来控制使用哪个日志记录绑定的问题。如果你想在运行时控制它,有点像编程,我想写一个小容器来启动你的应用程序是要走的路。但是,它仍然与DI无关。
答案 1 :(得分:1)
解决此问题的一个相当简单的方法是通过ILoggerFactory
方法将LoggerFactory
实例注入setILoggerFactory()
。 (截至2012年10月,setILoggerFactory()
方法不存在。)
SLF4J当前实现的静态绑定机制除了设置ILoggerFactory
之外没有什么用处。这种方法对你有用吗?
答案 2 :(得分:1)
对于现在发现这一点的任何人:Sangria实现一个"上下文敏感的绑定器"这对此很有效;具体见sangria-slf4j
和sangria-contextual
。
从the author's blog post开始,您可以像以下一样轻松设置SLF4J命名的记录器工厂:
public class YourModule extends AbstractModule {
@Override
protected void configure() {
install(new SangriaSlf4jModule());
}
}
...还有一些如何为您自己的类型使用新提供程序的示例。