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

咨询:如何将Kotlin Object作为Spigot注入点实现无依赖注入的Bukkit插件开发

Solution for Accessing Bukkit JavaPlugin Instance via Kotlin Object (No DI)

Absolutely! You can easily work around Bukkit's requirement for an instantiable main plugin class while using Kotlin objects for global access—no dependency injection needed. Here's a clean, idiomatic approach tailored to your use case:

Step 1: Create Your Instantiable Plugin Main Class

First, you still need a standard JavaPlugin subclass (Bukkit requires this to create an instance). In its onEnable method, you'll pass the plugin instance to a Kotlin singleton holder:

class MyKotlinPlugin : JavaPlugin() {
    override fun onEnable() {
        // Pass this instance to our singleton holder
        PluginSingletonHolder.instance = this
        logger.info("${name} enabled!")
    }

    override fun onDisable() {
        // Clean up the reference to avoid potential leaks
        PluginSingletonHolder.instance = null
        logger.info("${name} disabled!")
    }
}

Step 2: Create a Singleton Holder for the Plugin Instance

This object will act as a global store for your JavaPlugin instance. We add a convenience property to avoid null checks everywhere:

object PluginSingletonHolder {
    // Mark as volatile to ensure thread-safe visibility across Bukkit's scheduler threads
    @Volatile
    var instance: MyKotlinPlugin? = null

    // Throw a clear exception if someone tries to access before initialization
    val required: MyKotlinPlugin
        get() = instance ?: throw IllegalStateException(
            "Plugin instance not initialized! Make sure onEnable() has run."
        )
}

Step 3: Use the Instance in Your Library Code

Now you can access the plugin instance from any Kotlin object or class without constructor injection. Here are a couple of patterns:

Pattern 1: Wrapped Library API Object

Create a library-specific object that encapsulates common Bukkit operations using the plugin instance:

object MyLibraryAPI {
    // Shortcut to get the plugin instance safely
    private val plugin get() = PluginSingletonHolder.required

    // Example: Wrap Bukkit's broadcast method
    fun broadcastGlobalMessage(message: String) {
        plugin.server.broadcastMessage("[MyLibrary] $message")
    }

    // Example: Access plugin config
    fun getConfigSetting(key: String): String? {
        return plugin.config.getString(key)
    }

    // Expose direct access to Bukkit components if needed
    val server get() = plugin.server
    val logger get() = plugin.logger
}

Pattern 2: Base Class for Library Components

If your library has multiple classes that need the plugin instance, create an abstract base class to handle the instance lookup:

abstract class LibraryComponent {
    protected val plugin get() = PluginSingletonHolder.required

    // Common utility method for all components
    protected fun logInfo(message: String) {
        plugin.logger.info("[Library] $message")
    }
}

// Example component using the base class
class FeatureManager : LibraryComponent() {
    fun initializeFeature() {
        logInfo("Initializing core feature...")
        // Use the plugin instance for scheduler tasks, config, etc.
        plugin.scheduler.runTaskTimer(plugin, { /* Repeating task logic */ }, 0L, 20L)
    }
}

Key Notes for Stability

  • Thread Safety: The @Volatile annotation ensures the instance reference is visible across all threads (critical since Bukkit uses multiple scheduler threads).
  • Initialization Checks: The required property prevents silent NullPointerExceptions by throwing a clear error if the plugin hasn't been enabled yet.
  • Cleanup: Setting instance = null in onDisable() is a good practice to avoid accidental access after plugin shutdown, though Bukkit's class loader will eventually clean up the plugin's resources.

This approach keeps your code idiomatic to Kotlin, satisfies Bukkit's constraints, and avoids the overhead of dependency injection for your library.

内容的提问来源于stack exchange,提问作者stilbruch

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:55:21