我有一个Groovy脚本,它使用Grape@Grab
注解指定依赖项。指定的依赖项是spring-web
以使用RestTemplate
,并依赖于slf4j-nop
以避免Failed to load class "org.slf4j.impl.StaticLoggerBinder"
警告。
#!/usr/bin/env groovy
@Grab('org.springframework:spring-web:5.3.18')
@Grab('org.slf4j:slf4j-nop:1.7.36')
import org.springframework.web.client.RestTemplate
new RestTemplate().getForObject('http://www.example.com', String)
然而,尽管如此,我仍然得到SLF4J警告:
$ ./restTemplateLoggingTest.groovy
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
由于它是一个脚本,因此不要输出无关的噪声是很重要的,因为脚本输出可以通过编程方式使用和操作。
当我运行脚本时,我可以做些什么来防止输出此日志记录警告?
2条答案
按热度按时间ljo96ir51#
实验表明,使用
@GrabConfig(systemClassLoader=true)
将依赖项附加到系统类加载器会导致不再发出日志:我不知道为什么这是原因,虽然我有一些模糊的猜测。
请注意,尽管解决了这个问题,但这并不是
GrabConfig#systemClassLoader
的Javadocs所描述的用途:如果您想在加载葡萄时使用系统类加载器,则设置为true。这通常只在核心Java类需要引用抓取的类时才需要,例如例如,用于使用DriverManager访问的数据库驱动程序。
z6psavjg2#
简短版本:
根据M. Justin的回答,添加
@GrabConfig(systemClassLoader=true)
以在systemClassLoader上加载slf4j-nop
。但是,如果您计划在生产环境中使用它,请继续阅读下面的内容。
长版本:
从警告消息中的链接:
无法加载类org。slf4j.impl.StaticLoggerBinder当org.无法将slf4j.impl.StaticLoggerBinder类加载到内存中。当在类路径上找不到适当的SLF 4J绑定时,就会发生这种情况。
如果我们查看链中每个类加载器的类路径,我们可以看到spring和slf 4j jar在哪里。我们可以在提供的代码片段的末尾添加一段代码来实现:
输出将类似于:
我们可以看到spring-web(及其依赖项)存在于
groovy.lang.GroovyClassLoader
classpath中。然而,slf 4j-api也存在于父类加载器类路径(org.codehaus.groovy.tools.RootLoader
)中。典型的类加载器委托它们的父类来加载一个类。只有当父类失败时,类加载器才会尝试从类路径加载该类。影响:
当我们添加额外的配置
@GrabConfig(systemClassLoader=true)
systemClassLoader文档时,我们也指示将葡萄依赖项放在RootLoader上:如果您想在加载葡萄时使用系统类加载器,则设置为true。这通常只在核心Java类需要引用抓取的类时才需要,例如例如,用于使用DriverManager访问的数据库驱动程序。
输出:
slf 4j-api现在可以在类路径上找到SLF 4J绑定。
警告说明:值得一提的是,RootLoader中现在有两个版本的slf 4j-api,
slf4j-api-1.7.32
或slf4j-api-1.7.36
是否加载到内存中并不一定知道。它可能依赖于类加载器实现,依赖于jvm实现甚至依赖于操作系统。此外,如果在环境中加载哪些类的选择是确定性的,那么它仍然是一个实现细节,可能会在不同的系统上或随着平台升级而改变。
我不建议为了一个可靠的生产环境而在同一个类路径中保留相同类的两个版本。