From 5bf9fdf5b6833c22ef4592aa426d344da4245784 Mon Sep 17 00:00:00 2001 From: cssxsh Date: Fri, 28 Oct 2022 21:06:41 +0800 Subject: [PATCH] [console] feat: load SPI Service in jvm plugin (#2247) * feat: load SPI Service in jvm plugin * add: api dump * fix: docs --- .../compatibility-validation/jvm/api/jvm.api | 2 + .../src/plugin/jvm/AbstractJvmPlugin.kt | 44 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/mirai-console/backend/mirai-console/compatibility-validation/jvm/api/jvm.api b/mirai-console/backend/mirai-console/compatibility-validation/jvm/api/jvm.api index 417758581..21c8809ab 100644 --- a/mirai-console/backend/mirai-console/compatibility-validation/jvm/api/jvm.api +++ b/mirai-console/backend/mirai-console/compatibility-validation/jvm/api/jvm.api @@ -2236,6 +2236,8 @@ public abstract class net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin : net public final fun reloadPluginData (Lnet/mamoe/mirai/console/data/PluginData;)V public final fun savePluginConfig (Lnet/mamoe/mirai/console/data/PluginConfig;)V public final fun savePluginData (Lnet/mamoe/mirai/console/data/PluginData;)V + protected final fun services (Ljava/lang/Class;)Lkotlin/Lazy; + protected final synthetic fun services (Lkotlin/reflect/KClass;)Lkotlin/Lazy; } public final class net/mamoe/mirai/console/plugin/jvm/AbstractJvmPluginKt { diff --git a/mirai-console/backend/mirai-console/src/plugin/jvm/AbstractJvmPlugin.kt b/mirai-console/backend/mirai-console/src/plugin/jvm/AbstractJvmPlugin.kt index cc2680e20..57a3ad0fd 100644 --- a/mirai-console/backend/mirai-console/src/plugin/jvm/AbstractJvmPlugin.kt +++ b/mirai-console/backend/mirai-console/src/plugin/jvm/AbstractJvmPlugin.kt @@ -16,6 +16,7 @@ import net.mamoe.mirai.console.data.PluginConfig import net.mamoe.mirai.console.data.PluginData import net.mamoe.mirai.console.internal.plugin.JvmPluginClassLoaderN import net.mamoe.mirai.console.internal.plugin.JvmPluginInternal +import net.mamoe.mirai.console.internal.util.PluginServiceHelper import net.mamoe.mirai.console.permission.PermissionId import net.mamoe.mirai.console.permission.PermissionService import net.mamoe.mirai.console.util.ConsoleExperimentalApi @@ -23,6 +24,7 @@ import net.mamoe.mirai.utils.minutesToMillis import net.mamoe.mirai.utils.secondsToMillis import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext +import kotlin.reflect.KClass /** * [JavaPlugin] 和 [KotlinPlugin] 的父类. 所有 [JvmPlugin] 都应该拥有此类作为直接或间接父类. @@ -93,6 +95,48 @@ public abstract class AbstractJvmPlugin @JvmOverloads constructor( } error("jvmPluginClasspath not available for $classLoader") } + + /** + * 获取 指定类的 SPI Service + * + * 为了兼容 Kotlin object 单例类,此方法没有直接使用 java 原生的 API, + * 而是 手动读取 `META-INF/services/` 的内容, 并尝试构造或获取实例 + * + * 注: 仅包括当前插件 JAR 的 Service + */ + @JvmSynthetic + protected fun services(kClass: KClass): Lazy> = lazy { + val classLoader = try { + jvmPluginClasspath.pluginClassLoader + } catch (_: IllegalStateException) { + this::class.java.classLoader + } + with(PluginServiceHelper) { + classLoader + .findServices(kClass) + .loadAllServices() + } + } + + /** + * 获取 指定类的 SPI Service + * + * 为了兼容 Kotlin object 单例类,此方法没有直接使用 java 原生的 API, + * 而是 手动读取 `META-INF/services/` 的内容, 并尝试构造或获取实例 + * + * 注: 仅包括当前插件 JAR 的 Service + */ + protected fun services(clazz: Class): Lazy> = services(kClass = clazz.kotlin) + + /** + * 获取 指定类的 SPI Service + * + * 为了兼容 Kotlin object 单例类,此方法没有直接使用 java 原生的 API, + * 而是 手动读取 `META-INF/services/` 的内容, 并尝试构造或获取实例 + * + * 注: 仅包括当前插件 JAR 的 Service + */ + protected inline fun services(): Lazy> = services(kClass = T::class) } /**