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
andBridge
are server scoped,PacketConverter
andDisplayMessageConverter
were unscoped. If I try adding@ServerScope
toPacketConverter
I'm getting:error: [Dagger/IncompatiblyScopedBindings] org.craftit.runtime.MainComponent scoped with @Singleton may not reference bindings with different scopes
. This is weird, becausePacketConverter
is never created byMainComponent
.
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 可访问 类,你应该没事。