From b33133e4f2706c818a01d9e4f95ec8d294663158 Mon Sep 17 00:00:00 2001 From: gewuyou Date: Sat, 26 Jul 2025 11:56:33 +0800 Subject: [PATCH] =?UTF-8?q?refactor(plugin):=20=E9=87=8D=E6=9E=84=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E5=8A=A0=E8=BD=BD=E9=80=BB=E8=BE=91=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E9=A1=B9=E7=9B=AE=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改插件模块名称,统一命名规范 - 抽象出通用的 Spring 插件构建逻辑- 优化插件配置类加载方式 - 调整项目结构,提高可维护性 --- buildSrc/src/main/kotlin/Modules.kt | 2 +- .../plugin/demo/impl/SimpleGreetingPlugin.kt | 22 +++-- ...ture-6-support-plugin-modules-SNAPSHOT.jar | Bin 5088 -> 0 bytes ...geboot-plugin-demo-impl-0.1.1-SNAPSHOT.jar | Bin 0 -> 4732 bytes .../PluginInitializationException.kt | 15 ++++ .../plugin/spring/AbstractSpringPlugin.kt | 75 ++++++++++++++++++ .../plugin/spring/IsolatedSpringPlugin.kt | 22 +---- .../plugin/spring/MergedSpringPlugin.kt | 36 ++------- settings.gradle.kts | 4 +- 9 files changed, 115 insertions(+), 61 deletions(-) delete mode 100644 forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-server/plugins/forgeboot-plugin-demo-impl-0.0.7-feature-6-support-plugin-modules-SNAPSHOT.jar create mode 100644 forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-server/plugins/forgeboot-plugin-demo-impl-0.1.1-SNAPSHOT.jar create mode 100644 forgeboot-plugin/forgeboot-plugin-core/src/main/kotlin/com/gewuyou/forgeboot/plugin/core/exception/PluginInitializationException.kt create mode 100644 forgeboot-plugin/forgeboot-plugin-spring/src/main/kotlin/com/gewuyou/forgeboot/plugin/spring/AbstractSpringPlugin.kt diff --git a/buildSrc/src/main/kotlin/Modules.kt b/buildSrc/src/main/kotlin/Modules.kt index 4d2df04..5915d57 100644 --- a/buildSrc/src/main/kotlin/Modules.kt +++ b/buildSrc/src/main/kotlin/Modules.kt @@ -122,7 +122,7 @@ object Modules { } } object Plugin { - private const val PLUGIN = ":forgeboot-plugin" + private const val PLUGIN = ":forgeboot-plugin-spring-boot-starter" const val CORE = "${PLUGIN}:forgeboot-plugin-core" const val SPRING = "${PLUGIN}:forgeboot-plugin-spring" } diff --git a/forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-impl/src/main/kotlin/com/gewuyou/forgeboot/plugin/demo/impl/SimpleGreetingPlugin.kt b/forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-impl/src/main/kotlin/com/gewuyou/forgeboot/plugin/demo/impl/SimpleGreetingPlugin.kt index 7ecce7b..e6e5179 100644 --- a/forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-impl/src/main/kotlin/com/gewuyou/forgeboot/plugin/demo/impl/SimpleGreetingPlugin.kt +++ b/forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-impl/src/main/kotlin/com/gewuyou/forgeboot/plugin/demo/impl/SimpleGreetingPlugin.kt @@ -1,10 +1,7 @@ package com.gewuyou.forgeboot.plugin.demo.impl -import com.gewuyou.forgeboot.plugin.spring.manager.SpringPluginManager +import com.gewuyou.forgeboot.plugin.spring.MergedSpringPlugin import org.pf4j.PluginWrapper -import org.pf4j.spring.SpringPlugin -import org.springframework.context.ApplicationContext -import org.springframework.context.annotation.AnnotationConfigApplicationContext /** * 简单的问候插件 @@ -16,13 +13,14 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext */ class SimpleGreetingPlugin( private val pluginWrapper: PluginWrapper, -) : SpringPlugin(pluginWrapper) { - override fun createApplicationContext(): ApplicationContext { - return AnnotationConfigApplicationContext().apply { -> - classLoader = pluginWrapper.pluginClassLoader - parent = (pluginWrapper.pluginManager as SpringPluginManager).applicationContext - register(PluginConfig::class.java) - refresh() - } +) : MergedSpringPlugin(pluginWrapper) { + /** + * 获取插件配置类 + * + * 抽象方法,子类需要提供插件特定的配置类, + * 该配置类将被注册到插件的应用上下文中。 + */ + override fun pluginConfigurationClass(): List> { + return listOf(PluginConfig::class.java) } } \ No newline at end of file diff --git a/forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-server/plugins/forgeboot-plugin-demo-impl-0.0.7-feature-6-support-plugin-modules-SNAPSHOT.jar b/forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-server/plugins/forgeboot-plugin-demo-impl-0.0.7-feature-6-support-plugin-modules-SNAPSHOT.jar deleted file mode 100644 index 680394a49ae1cf416325720dd8540444b2691ecb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5088 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 diff --git a/forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-server/plugins/forgeboot-plugin-demo-impl-0.1.1-SNAPSHOT.jar b/forgeboot-demo/forgeboot-plugin-demo/forgeboot-plugin-demo-server/plugins/forgeboot-plugin-demo-impl-0.1.1-SNAPSHOT.jar new file mode 100644 index 0000000000000000000000000000000000000000..8fcf8c586c1b19286a19c5b20e4ee0dc8a884207 GIT binary patch literal 4732 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 literal 0 HcmV?d00001 diff --git a/forgeboot-plugin/forgeboot-plugin-core/src/main/kotlin/com/gewuyou/forgeboot/plugin/core/exception/PluginInitializationException.kt b/forgeboot-plugin/forgeboot-plugin-core/src/main/kotlin/com/gewuyou/forgeboot/plugin/core/exception/PluginInitializationException.kt new file mode 100644 index 0000000..7c56c64 --- /dev/null +++ b/forgeboot-plugin/forgeboot-plugin-core/src/main/kotlin/com/gewuyou/forgeboot/plugin/core/exception/PluginInitializationException.kt @@ -0,0 +1,15 @@ +package com.gewuyou.forgeboot.plugin.core.exception + +/** + *插件初始化异常 + * + * @since 2025-07-26 11:25:18 + * @author gewuyou + */ +class PluginInitializationException( + message: String, + cause: Throwable?, +) : RuntimeException( + message, + cause +) \ No newline at end of file diff --git a/forgeboot-plugin/forgeboot-plugin-spring/src/main/kotlin/com/gewuyou/forgeboot/plugin/spring/AbstractSpringPlugin.kt b/forgeboot-plugin/forgeboot-plugin-spring/src/main/kotlin/com/gewuyou/forgeboot/plugin/spring/AbstractSpringPlugin.kt new file mode 100644 index 0000000..ff7f86a --- /dev/null +++ b/forgeboot-plugin/forgeboot-plugin-spring/src/main/kotlin/com/gewuyou/forgeboot/plugin/spring/AbstractSpringPlugin.kt @@ -0,0 +1,75 @@ +package com.gewuyou.forgeboot.plugin.spring + +import com.gewuyou.forgeboot.plugin.core.exception.PluginInitializationException +import org.pf4j.PluginWrapper +import org.pf4j.spring.SpringPlugin +import org.springframework.context.ApplicationContext +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.core.env.ConfigurableEnvironment + +/** + *抽象Spring插件 + * + * @since 2025-07-26 11:27:26 + * @author gewuyou + */ +abstract class AbstractSpringPlugin( + pluginWrapper: PluginWrapper, +) : SpringPlugin(pluginWrapper) { + /** + * 获取插件配置类 + * + * 抽象方法,子类需要提供插件特定的配置类, + * 该配置类将被注册到插件的应用上下文中。 + */ + abstract fun pluginConfigurationClass(): List> + + /** + * 构建Spring应用上下文 + * + * 该函数用于创建并配置一个AnnotationConfigApplicationContext实例, + * 包括设置类加载器、父上下文、环境配置,注册配置类并刷新上下文。 + * + * @param pluginWrapper 插件包装器,提供插件的基本信息和类加载器 + * @param parentContext 父级应用上下文,可为空 + * @param environment 可选的环境配置 + * @return 配置完成的AnnotationConfigApplicationContext实例 + */ + protected fun buildSpringContext( + pluginWrapper: PluginWrapper, + parentContext: ApplicationContext? = null, + environment: ConfigurableEnvironment? = null, + ): AnnotationConfigApplicationContext { + try { + val configClasses = pluginConfigurationClass().also { + require(it.isNotEmpty()) { + "插件 [${pluginWrapper.pluginId}] 未提供任何配置类" + } + } + + return AnnotationConfigApplicationContext().apply { + // 设置插件类加载器 + classLoader = pluginWrapper.pluginClassLoader + // 设置父级上下文 + parent = parentContext + // 如果提供了环境配置,则设置环境 + if (environment != null) { + this.environment = environment + } + // 注册所有配置类 + configClasses.forEach { register(it) } + // 刷新上下文以完成初始化 + refresh() + log.info( + "✅ 插件 [{}] 上下文加载成功,注册配置类: {}", + pluginWrapper.pluginId, + configClasses.joinToString() + ) + } + } catch (e: Exception) { + log.error("❌ 插件 [{}] 加载失败", pluginWrapper.pluginId, e) + throw PluginInitializationException("插件 [${pluginWrapper.pluginId}] 初始化失败", e) + } + } + +} \ No newline at end of file diff --git a/forgeboot-plugin/forgeboot-plugin-spring/src/main/kotlin/com/gewuyou/forgeboot/plugin/spring/IsolatedSpringPlugin.kt b/forgeboot-plugin/forgeboot-plugin-spring/src/main/kotlin/com/gewuyou/forgeboot/plugin/spring/IsolatedSpringPlugin.kt index 120802f..e4edcf9 100644 --- a/forgeboot-plugin/forgeboot-plugin-spring/src/main/kotlin/com/gewuyou/forgeboot/plugin/spring/IsolatedSpringPlugin.kt +++ b/forgeboot-plugin/forgeboot-plugin-spring/src/main/kotlin/com/gewuyou/forgeboot/plugin/spring/IsolatedSpringPlugin.kt @@ -1,9 +1,7 @@ package com.gewuyou.forgeboot.plugin.spring import org.pf4j.PluginWrapper -import org.pf4j.spring.SpringPlugin import org.springframework.context.ApplicationContext -import org.springframework.context.annotation.AnnotationConfigApplicationContext /** * 隔离的Spring插件 @@ -17,8 +15,8 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext * @author gewuyou */ abstract class IsolatedSpringPlugin( - private val pluginWrapper: PluginWrapper -) : SpringPlugin(pluginWrapper) { + private val pluginWrapper: PluginWrapper, +) : AbstractSpringPlugin(pluginWrapper) { /** * 创建应用上下文 @@ -29,20 +27,6 @@ abstract class IsolatedSpringPlugin( * @return 配置完成的ApplicationContext实例 */ override fun createApplicationContext(): ApplicationContext { - return AnnotationConfigApplicationContext().apply { - classLoader = pluginWrapper.pluginClassLoader - register(pluginConfigurationClass()) - refresh() - } + return buildSpringContext(pluginWrapper) } - - /** - * 获取插件配置类 - * - * 抽象方法,子类需要提供插件特定的配置类, - * 该配置类将被注册到插件的应用上下文中。 - * - * @return 插件配置类的Class对象 - */ - abstract fun pluginConfigurationClass(): Class<*> } \ No newline at end of file diff --git a/forgeboot-plugin/forgeboot-plugin-spring/src/main/kotlin/com/gewuyou/forgeboot/plugin/spring/MergedSpringPlugin.kt b/forgeboot-plugin/forgeboot-plugin-spring/src/main/kotlin/com/gewuyou/forgeboot/plugin/spring/MergedSpringPlugin.kt index 7c6f120..17544eb 100644 --- a/forgeboot-plugin/forgeboot-plugin-spring/src/main/kotlin/com/gewuyou/forgeboot/plugin/spring/MergedSpringPlugin.kt +++ b/forgeboot-plugin/forgeboot-plugin-spring/src/main/kotlin/com/gewuyou/forgeboot/plugin/spring/MergedSpringPlugin.kt @@ -1,10 +1,8 @@ package com.gewuyou.forgeboot.plugin.spring import org.pf4j.PluginWrapper -import org.pf4j.spring.SpringPlugin import org.pf4j.spring.SpringPluginManager import org.springframework.context.ApplicationContext -import org.springframework.context.annotation.AnnotationConfigApplicationContext import org.springframework.core.env.ConfigurableEnvironment /** @@ -17,38 +15,20 @@ import org.springframework.core.env.ConfigurableEnvironment * @property pluginWrapper 插件包装器,提供插件的基本信息和类加载器 * * @since 2025-07-24 15:35:52 - * @author gewuyou */ abstract class MergedSpringPlugin( - private val pluginWrapper: PluginWrapper -) : SpringPlugin(pluginWrapper) { - + private val pluginWrapper: PluginWrapper, +) : AbstractSpringPlugin(pluginWrapper) { /** * 创建应用上下文 * - * 该方法覆盖了父类的实现,创建一个与主应用上下文有关联的AnnotationConfigApplicationContext, - * 设置插件的类加载器,建立父子上下文关系,并注册插件特定的配置类。 - * - * @return 配置完成的ApplicationContext实例 + * 创建一个与主应用上下文有关联的 AnnotationConfigApplicationContext, + * 设置类加载器、父上下文、环境,并注册插件配置类。 */ override fun createApplicationContext(): ApplicationContext { - return AnnotationConfigApplicationContext().apply { - classLoader = pluginWrapper.pluginClassLoader - parent = (pluginWrapper.pluginManager as SpringPluginManager).applicationContext - // 保证配置文件能读取 - environment = parent?.environment as ConfigurableEnvironment - register(pluginConfigurationClass()) - refresh() - } + val manager = pluginWrapper.pluginManager as SpringPluginManager + val parentCtx = manager.applicationContext + val env = parentCtx.environment as ConfigurableEnvironment + return buildSpringContext(pluginWrapper, parentCtx, env) } - - /** - * 获取插件配置类 - * - * 抽象方法,子类需要提供插件特定的配置类, - * 该配置类将被注册到插件的应用上下文中。 - * - * @return 插件配置类的Class对象 - */ - abstract fun pluginConfigurationClass(): Class<*> } \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index fccbead..e15540c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -157,7 +157,9 @@ include( ":forgeboot-plugin:forgeboot-plugin-core", ":forgeboot-plugin:forgeboot-plugin-spring", ) - +project(":forgeboot-plugin").name = "forgeboot-plugin-spring-boot-starter" +project(":forgeboot-plugin:forgeboot-plugin-core").name = "forgeboot-plugin-core" +project(":forgeboot-plugin:forgeboot-plugin-spring").name = "forgeboot-plugin-spring" //region module cache include( "forgeboot-cache",