Merge branch 'refactor/9-optimize-plugin-module-code' into 'main'

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

Closes #9

See merge request gewuyou/forgeboot!14
This commit is contained in:
gewuyou 2025-07-26 03:58:58 +00:00
commit 2893b5278a
9 changed files with 115 additions and 61 deletions

View File

@ -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"
}

View File

@ -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<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
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<*>
}

View File

@ -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<*>
}

View File

@ -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",