Equinox集成SLF4J无法找到Logback Provider问题求助
我有一个基于Equinox构建的OSGi项目,Gradle项目结构如下:
> Task :projects ------------------------------------------------------------ Root project 'project' ------------------------------------------------------------ Root project 'project' No sub-projects Included builds +--- Included build ':callable-processor' +--- Included build ':osgi-sun-misc' +--- Included build ':path-collector' +--- Included build ':robot-api' +--- Included build ':robot-equinox' +--- Included build ':robot-signal' +--- Included build ':robot-instance' +--- Included build ':utils' \--- Included build ':reactive'
主bundle为robot-equinox。
根项目project的build.gradle配置:
// project ext.baseVersion = '2.0.0' ext.buildTag = "SNAPSHOT" group 'project' version "${baseVersion}-${buildTag}" project { quality = ALFA } configurations { bundleInstall bundleStart misc } dependencies { bundleInstall 'ch.qos.logback:logback-classic:1.3.5' bundleInstall 'ch.qos.logback:logback-core:1.3.5' bundleInstall 'org.slf4j:slf4j-api:2.0.5' bundleInstall 'org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle:1.3.5' bundleInstall 'prodist:callable-processor' bundleInstall 'prodist:osgi-sun-misc' bundleInstall 'prodist:path-collector' bundleInstall 'prodist:reactive' bundleInstall 'prodist:robot-api' bundleStart 'ch.qos.logback:logback-classic:1.3.5' bundleStart 'ch.qos.logback:logback-core:1.3.5' bundleStart 'org.slf4j:slf4j-api:2.0.5' bundleStart 'prodist:robot-equinox' }
robot-equinox模块的build.gradle配置:
dependencies { implementation group: 'prodist', name: 'callable-processor' implementation group: 'prodist', name: 'path-collector' implementation group: 'prodist', name: 'robot-api' implementation group: 'prodist', name: 'reactive' implementation group: 'prodist', name: 'robot-instance' implementation group: 'prodist', name: 'utils' compileOnly group: 'org.osgi', name: 'osgi.core', version: '6.0.0' testImplementation group: 'org.hamcrest', name: 'hamcrest', version: '2.2' testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.2.4' testImplementation group: 'org.reactivestreams', name: 'reactive-streams-tck', version: '1.0.3' testImplementation group: 'org.testng', name: 'testng', version: '7.1.0' testCompileOnly group: 'org.osgi', name: 'osgi.core', version: '6.0.0' }
主类Application.java的日志相关代码:
package project.robot.equinox; import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; public class Application { private static final Logger logger = LoggerFactory.getLogger(Application.class); public Application () { MDC.put("product.name", ProductInfo.getName()); MDC.put("product.version", ProductInfo.getVersion()); } public void activate (BundleContext bundleContext) { logger.atTrace().log("activate: enter"); } // 其他代码省略 }
启动应用时,OSGi控制台输出以下错误:
osgi> SLF4J: No SLF4J providers were found. SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
我已经安装了SLF4J和Logback,但SLF4J无法自动识别Logback实现,请问该如何解决?
在OSGi环境下,SLF4J的SPI机制不能像普通Java应用那样直接工作,需要结合OSGi的bundle特性调整配置,以下是具体解决步骤:
1. 调整bundle启动顺序
你已经引入了org.apache.aries.spifly.dynamic.bundle,它负责在OSGi中处理SPI服务发现,必须让它在SLF4J和Logback之前启动。修改根项目的bundleStart依赖顺序:
bundleStart 'org.apache.aries.spifly:org.apache.aries.spifly.dynamic.bundle:1.3.5' bundleStart 'ch.qos.logback:logback-core:1.3.5' bundleStart 'ch.qos.logback:logback-classic:1.3.5' bundleStart 'org.slf4j:slf4j-api:2.0.5' bundleStart 'prodist:robot-equinox'
2. 配置SPIFly扫描SLF4J Provider
给SPIFly添加启动参数,明确指定要扫描的SLF4J相关bundle:
如果使用Gradle的OSGi启动插件,在根项目build.gradle中添加:
tasks.withType(org.gradle.osgi.run.OSGiRun) { args += [ '-Dorg.apache.aries.spifly.selective.validation=relaxed', '-Dorg.apache.aries.spifly.bundle.selector=ch.qos.logback.classic', '-Dorg.apache.aries.spifly.staticbundle.selector=org.slf4j,ch.qos.logback.core' ] }
如果是通过控制台启动,直接在启动命令中加入这些JVM参数即可。
3. 完善Robot-Equinox的依赖声明
在robot-equinox的build.gradle中添加SLF4J和Logback的依赖,确保OSGi能正确解析服务:
dependencies { // 保留原有依赖 implementation 'org.slf4j:slf4j-api:2.0.5' implementation 'ch.qos.logback:logback-classic:1.3.5' implementation 'ch.qos.logback:logback-core:1.3.5' }
若使用Gradle OSGi插件,它会自动生成MANIFEST.MF中的导入声明,无需手动编写。
4. 验证bundle状态
启动应用后,在OSGi控制台执行ss命令,检查以下bundle是否处于ACTIVE状态:
- org.apache.aries.spifly.dynamic.bundle
- ch.qos.logback.core
- ch.qos.logback.classic
- org.slf4j.api
- prodist.robot-equinox
如果有bundle处于INSTALLED或RESOLVED状态,执行start <bundle-id>手动启动,查看控制台输出的错误信息,针对性解决依赖缺失问题。
内容的提问来源于stack exchange,提问作者skrenato

