error: [Dagger/MissingBinding] error message doesn't make sense

error: [Dagger/MissingBinding] error message doesn't make sense

我得到:

C:\Users\Gieted\Projekty\CraftIt\runtime\build\tmp\kapt3\stubs\main\org\craftit\runtime\MainComponent.java:8: error: [Dagger/MissingBinding] java.lang.ClassLoader cannot be provided without an @Provides-annotated method.
public abstract interface MainComponent {
                ^
  A binding with matching key exists in component: org.craftit.runtime.server.ServerComponent
      java.lang.ClassLoader is injected at
          org.craftit.runtime.resources.packets.converters.DisplayMessageConverter(�, classLoader, �)
      org.craftit.runtime.resources.packets.converters.DisplayMessageConverter is injected at
          org.craftit.runtime.resources.packets.converters.PacketConverter(�, displayMessageConverter)
      org.craftit.runtime.resources.packets.converters.PacketConverter is injected at
          org.craftit.runtime.Bridge(�, packetConverter, �)
      org.craftit.runtime.Bridge is injected at
          org.craftit.runtime.server.initializers.VanillaServerInitializer(bridge, �)
      org.craftit.runtime.server.initializers.VanillaServerInitializer is injected at
          org.craftit.runtime.server.ServerModule.nativeServerInitializer(to)
      org.craftit.runtime.server.initializers.NativeServerInitializer is requested at
          org.craftit.runtime.server.ServerComponent.nativeServerInitializer() [org.craftit.runtime.MainComponent ? org.craftit.runtime.server.ServerComponent]
  It is also requested at:
      org.craftit.runtime.resources.entities.player.ChatType(�, classLoader)
      org.craftit.runtime.resources.entities.player.NativeConnectorImpl(�, classLoader)
      org.craftit.runtime.resources.packets.converters.SendChatMessageConverter(�, classLoader)
      org.craftit.runtime.text.NativeColorFactory(�, classLoader)
      org.craftit.runtime.text.StringTextComponentFactory(�, classLoader, �)
      org.craftit.runtime.text.StyleFactory(�, classLoader, �)
  The following other entry points also depend on it:
      org.craftit.runtime.server.ServerComponent.entityRegistry() [org.craftit.runtime.MainComponent ? org.craftit.runtime.server.ServerComponent]

所以“A binding with matching key exists in component: org.craftit.runtime.server.ServerComponent”表明请求的绑定在ServerComponent中找到,但同时is requested at org.craftit.runtime.server.ServerComponent.nativeServerInitializer()告诉缺少的绑定来自ServerComponent,这没有任何意义。谁能给我解释一下这是怎么回事,我应该在哪里搜索错误?

@ServerScope
@Subcomponent(modules = [ServerModule::class])
interface ServerComponent {

    fun pluginLoader(): PluginLoader

    fun entityRegistry(): EntityRegistry

    fun nativeServerInitializer(): NativeServerInitializer

    fun commandRegistry(): CommandRegistry

    fun pluginRegistry(): PluginRegistry

    @Subcomponent.Factory
    interface Factory {
        fun create(@BindsInstance server: Server): ServerComponent
    }
}
@Singleton
@Component(modules = [MainModule::class])
interface MainComponent {

    @Named("new")
    fun server(): Server

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance configuration: Configuration): MainComponent
    }
}
class VanillaServer @Inject constructor(
    serverComponentFactory: ServerComponent.Factory
) : Server {

    override val entities: EntityRegistry
    override val commands: CommandRegistry
    override val plugins: PluginRegistry

    private val pluginLoader: PluginLoader

    private val nativeServerInitializer: NativeServerInitializer

    init {
        val component = serverComponentFactory.create(this)
        pluginLoader = component.pluginLoader()
        entities = component.entityRegistry()
        nativeServerInitializer = component.nativeServerInitializer()
        commands = component.commandRegistry()
        plugins = component.pluginRegistry()
    }

    override fun start() {
        nativeServerInitializer.startServer()
        pluginLoader.loadPlugins()
        plugins.forEach { it.enable() }
    }
}
@Module
abstract class ServerModule {
    companion object {
        @Provides
        @ServerScope
        fun classLoader(configuration: Configuration): ClassLoader =
            URLClassLoader(arrayOf(configuration.serverFile.toURI().toURL()))
    }

    @Binds
    @ServerScope
    abstract fun entityRegistry(to: VanillaEntityRegistry): EntityRegistry

    @Binds
    @ServerScope
    abstract fun nativeServerInitializer(to: VanillaServerInitializer): NativeServerInitializer
}

真正的问题远在第一行的右侧:

MainComponent.java:8: error: [Dagger/MissingBinding] java.lang.ClassLoader cannot be provided without an @Provides-annotated method.

您可以看到它在 ServerModule 中提供,但您收到消息是因为无法从 MainComponent 访问您在 ServerComponent 中提供的类加载器。这是有道理的:来自 MainComponent 的绑定可在 ServerComponent 中访问,但 ServerComponent 中的绑定在 MainComponent 中不可访问,除非通过您通过 ServerComponent 的工厂创建的特定 ServerComponent 实例检索。

这也是您的解决方案有效的原因:

VanillaServerInitializer and Bridge are server scoped, PacketConverter and DisplayMessageConverter were unscoped. If I try adding @ServerScope to PacketConverter I'm getting: error: [Dagger/IncompatiblyScopedBindings] org.craftit.runtime.MainComponent scoped with @Singleton may not reference bindings with different scopes. This is weird, because PacketConverter is never created by MainComponent.

Setting either singleton or server scope on every binding fixed the issue. But why have it happened in the first place?

由于您的 PacketConverter 和 DisplayMessageConverter 没有作用域,Dagger 尝试在无法提供 ClassLoader 的 MainComponent 中实现它们。 (如果可能的话,我也希望 PacketConverter 在 ServerComponent 中实现,但是你所描述的将更符合从 MainComponent 的绑定通过 @Named("new") Server 或 MainModule 中的绑定在某处传递访问它你漏了。)

在任何情况下,只要您只尝试从 @ServerScoped 和无作用域 类 访问您的绑定,永远不要从 @Singleton 或 MainComponent 可访问 类,你应该没事。