refactor(plugin): 重构插件加载逻辑并优化项目结构

- 修改插件模块名称,统一命名规范
- 抽象出通用的 Spring 插件构建逻辑- 优化插件配置类加载方式
- 调整项目结构,提高可维护性
This commit is contained in:
gewuyou 2025-07-26 11:56:33 +08:00
parent 1e3f17d42f
commit b33133e4f2
9 changed files with 115 additions and 61 deletions

View File

@ -122,7 +122,7 @@ object Modules {
} }
} }
object Plugin { 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 CORE = "${PLUGIN}:forgeboot-plugin-core"
const val SPRING = "${PLUGIN}:forgeboot-plugin-spring" const val SPRING = "${PLUGIN}:forgeboot-plugin-spring"
} }

View File

@ -1,10 +1,7 @@
package com.gewuyou.forgeboot.plugin.demo.impl 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.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( class SimpleGreetingPlugin(
private val pluginWrapper: PluginWrapper, private val pluginWrapper: PluginWrapper,
) : SpringPlugin(pluginWrapper) { ) : MergedSpringPlugin(pluginWrapper) {
override fun createApplicationContext(): ApplicationContext { /**
return AnnotationConfigApplicationContext().apply { -> * 获取插件配置类
classLoader = pluginWrapper.pluginClassLoader *
parent = (pluginWrapper.pluginManager as SpringPluginManager).applicationContext * 抽象方法子类需要提供插件特定的配置类
register(PluginConfig::class.java) * 该配置类将被注册到插件的应用上下文中
refresh() */
} override fun pluginConfigurationClass(): List<Class<*>> {
return listOf(PluginConfig::class.java)
} }
} }

View File

@ -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
)

View File

@ -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<Class<*>>
/**
* 构建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)
}
}
}

View File

@ -1,9 +1,7 @@
package com.gewuyou.forgeboot.plugin.spring package com.gewuyou.forgeboot.plugin.spring
import org.pf4j.PluginWrapper import org.pf4j.PluginWrapper
import org.pf4j.spring.SpringPlugin
import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContext
import org.springframework.context.annotation.AnnotationConfigApplicationContext
/** /**
* 隔离的Spring插件 * 隔离的Spring插件
@ -17,8 +15,8 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
* @author gewuyou * @author gewuyou
*/ */
abstract class IsolatedSpringPlugin( abstract class IsolatedSpringPlugin(
private val pluginWrapper: PluginWrapper private val pluginWrapper: PluginWrapper,
) : SpringPlugin(pluginWrapper) { ) : AbstractSpringPlugin(pluginWrapper) {
/** /**
* 创建应用上下文 * 创建应用上下文
@ -29,20 +27,6 @@ abstract class IsolatedSpringPlugin(
* @return 配置完成的ApplicationContext实例 * @return 配置完成的ApplicationContext实例
*/ */
override fun createApplicationContext(): ApplicationContext { override fun createApplicationContext(): ApplicationContext {
return AnnotationConfigApplicationContext().apply { return buildSpringContext(pluginWrapper)
classLoader = pluginWrapper.pluginClassLoader
register(pluginConfigurationClass())
refresh()
} }
} }
/**
* 获取插件配置类
*
* 抽象方法子类需要提供插件特定的配置类
* 该配置类将被注册到插件的应用上下文中
*
* @return 插件配置类的Class对象
*/
abstract fun pluginConfigurationClass(): Class<*>
}

View File

@ -1,10 +1,8 @@
package com.gewuyou.forgeboot.plugin.spring package com.gewuyou.forgeboot.plugin.spring
import org.pf4j.PluginWrapper import org.pf4j.PluginWrapper
import org.pf4j.spring.SpringPlugin
import org.pf4j.spring.SpringPluginManager import org.pf4j.spring.SpringPluginManager
import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationContext
import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.core.env.ConfigurableEnvironment import org.springframework.core.env.ConfigurableEnvironment
/** /**
@ -17,38 +15,20 @@ import org.springframework.core.env.ConfigurableEnvironment
* @property pluginWrapper 插件包装器提供插件的基本信息和类加载器 * @property pluginWrapper 插件包装器提供插件的基本信息和类加载器
* *
* @since 2025-07-24 15:35:52 * @since 2025-07-24 15:35:52
* @author gewuyou
*/ */
abstract class MergedSpringPlugin( abstract class MergedSpringPlugin(
private val pluginWrapper: PluginWrapper private val pluginWrapper: PluginWrapper,
) : SpringPlugin(pluginWrapper) { ) : AbstractSpringPlugin(pluginWrapper) {
/** /**
* 创建应用上下文 * 创建应用上下文
* *
* 该方法覆盖了父类的实现创建一个与主应用上下文有关联的AnnotationConfigApplicationContext * 创建一个与主应用上下文有关联的 AnnotationConfigApplicationContext
* 设置插件的类加载器建立父子上下文关系并注册插件特定的配置类 * 设置类加载器父上下文环境并注册插件配置类
*
* @return 配置完成的ApplicationContext实例
*/ */
override fun createApplicationContext(): ApplicationContext { override fun createApplicationContext(): ApplicationContext {
return AnnotationConfigApplicationContext().apply { val manager = pluginWrapper.pluginManager as SpringPluginManager
classLoader = pluginWrapper.pluginClassLoader val parentCtx = manager.applicationContext
parent = (pluginWrapper.pluginManager as SpringPluginManager).applicationContext val env = parentCtx.environment as ConfigurableEnvironment
// 保证配置文件能读取 return buildSpringContext(pluginWrapper, parentCtx, env)
environment = parent?.environment as ConfigurableEnvironment
register(pluginConfigurationClass())
refresh()
} }
} }
/**
* 获取插件配置类
*
* 抽象方法子类需要提供插件特定的配置类
* 该配置类将被注册到插件的应用上下文中
*
* @return 插件配置类的Class对象
*/
abstract fun pluginConfigurationClass(): Class<*>
}

View File

@ -157,7 +157,9 @@ include(
":forgeboot-plugin:forgeboot-plugin-core", ":forgeboot-plugin:forgeboot-plugin-core",
":forgeboot-plugin:forgeboot-plugin-spring", ":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 //region module cache
include( include(
"forgeboot-cache", "forgeboot-cache",