You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 10:20:36