Skip to content

Commit

Permalink
feat: improve dependency injection for plugins with separate context
Browse files Browse the repository at this point in the history
  • Loading branch information
duruer committed Mar 25, 2024
1 parent 8e2ae68 commit 865cbc6
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 23 deletions.
7 changes: 5 additions & 2 deletions src/main/kotlin/co/statu/parsek/PluginFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,19 @@ class PluginFactory : DefaultPluginFactory() {
plugin.pluginEventManager = pluginEventManager
plugin.environmentType = Main.ENVIRONMENT
plugin.releaseStage = Main.STAGE
plugin.pluginGlobalBeanContext = PluginManager.pluginGlobalBeanContext
plugin.applicationContext = Main.applicationContext

val pluginBeanContext by lazy {
val pluginBeanContext = AnnotationConfigApplicationContext()

pluginBeanContext.parent = Main.applicationContext
pluginBeanContext.setAllowBeanDefinitionOverriding(true)

pluginBeanContext.parent = PluginManager.pluginGlobalBeanContext
pluginBeanContext.classLoader = pluginClass.classLoader
pluginBeanContext.scan(pluginClass.`package`.name)

pluginBeanContext.beanFactory.registerSingleton(logger.javaClass.name, logger)
pluginBeanContext.beanFactory.registerSingleton(plugin.logger.javaClass.name, plugin.logger)
pluginBeanContext.beanFactory.registerSingleton(pluginEventManager.javaClass.name, pluginEventManager)
pluginBeanContext.beanFactory.registerSingleton(plugin.javaClass.name, plugin)

Expand Down
13 changes: 13 additions & 0 deletions src/main/kotlin/co/statu/parsek/PluginManager.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
package co.statu.parsek

import org.pf4j.*
import org.springframework.context.annotation.AnnotationConfigApplicationContext
import java.nio.file.Path

class PluginManager(importPaths: List<Path>) : DefaultPluginManager(importPaths) {
companion object {
internal val pluginEventManager = PluginEventManager()

internal val pluginGlobalBeanContext by lazy {
val pluginGlobalBeanContext = AnnotationConfigApplicationContext()

pluginGlobalBeanContext.setAllowBeanDefinitionOverriding(true)

pluginGlobalBeanContext.beanFactory.registerSingleton(SpringConfig.vertx.javaClass.name, SpringConfig.vertx)

pluginGlobalBeanContext.refresh()

pluginGlobalBeanContext
}
}

override fun createPluginDescriptorFinder(): CompoundPluginDescriptorFinder {
Expand Down
5 changes: 3 additions & 2 deletions src/main/kotlin/co/statu/parsek/SpringConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ open class SpringConfig {
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
open fun router(
schemaParser: SchemaParser,
configManager: ConfigManager
configManager: ConfigManager,
pluginManager: PluginManager
) =
RouterProvider.create(vertx, applicationContext, schemaParser, configManager)
RouterProvider.create(vertx, applicationContext, schemaParser, configManager, pluginManager)
.provide()

@Bean
Expand Down
23 changes: 10 additions & 13 deletions src/main/kotlin/co/statu/parsek/api/ParsekPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,21 @@ abstract class ParsekPlugin : Plugin() {
lateinit var pluginBeanContext: AnnotationConfigApplicationContext
internal set

lateinit var pluginGlobalBeanContext: AnnotationConfigApplicationContext
internal set

internal lateinit var applicationContext: AnnotationConfigApplicationContext

val logger: Logger = LoggerFactory.getLogger(this::class.java)

private val registeredBeans = mutableListOf<Class<*>>()
private val registeredBeans = mutableListOf<Any>()

fun register(bean: Class<*>) {
fun registerSingletonGlobal(bean: Any) {
if (registeredBeans.contains(bean)) {
return
}

applicationContext.register(bean)
pluginGlobalBeanContext.beanFactory.registerSingleton(bean.javaClass.name, bean)

registeredBeans.add(bean)
}
Expand All @@ -46,20 +49,14 @@ abstract class ParsekPlugin : Plugin() {
pluginEventManager.register(this, eventListener)
}

fun unRegister(bean: Class<*>) {
fun unRegisterGlobal(bean: Any) {
if (!registeredBeans.contains(bean)) {
return
}

val registry = applicationContext.beanFactory as BeanDefinitionRegistry
val beanNames = registry.beanDefinitionNames
val registry = pluginGlobalBeanContext.beanFactory as BeanDefinitionRegistry

for (beanName in beanNames) {
if (registry.getBeanDefinition(beanName).beanClassName == bean.name) {
registry.removeBeanDefinition(beanName)
return // Stop after removing the first bean definition of the given class
}
}
registry.removeBeanDefinition(bean.javaClass.name)

registeredBeans.remove(bean)
}
Expand All @@ -82,7 +79,7 @@ abstract class ParsekPlugin : Plugin() {
val copyOfRegisteredBeans = registeredBeans.toList()

copyOfRegisteredBeans.forEach {
unRegister(it)
unRegisterGlobal(it)
}

pluginEventManager.unregisterPlugin(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ import co.statu.parsek.config.ConfigManager
import com.google.gson.Gson
import io.vertx.core.json.JsonObject
import org.slf4j.Logger
import org.slf4j.LoggerFactory

class PluginConfigManager<T : PluginConfig>(
private val configManager: ConfigManager,
plugin: ParsekPlugin,
private val pluginConfigClass: Class<T>,
private val logger: Logger,
private val migrations: List<PluginConfigMigration> = listOf(),
private val exPluginIds: List<String> = listOf()
) {
private val logger: Logger = LoggerFactory.getLogger(this::class.java)

companion object {
private val gson = Gson()
}
Expand Down
20 changes: 15 additions & 5 deletions src/main/kotlin/co/statu/parsek/route/RouterProvider.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package co.statu.parsek.route

import co.statu.parsek.PluginEventManager
import co.statu.parsek.PluginManager
import co.statu.parsek.annotation.Endpoint
import co.statu.parsek.api.ParsekPlugin
import co.statu.parsek.api.event.RouterEventListener
import co.statu.parsek.config.ConfigManager
import co.statu.parsek.model.Api
Expand All @@ -14,22 +16,25 @@ import io.vertx.ext.web.handler.CorsHandler
import io.vertx.ext.web.handler.SessionHandler
import io.vertx.ext.web.sstore.LocalSessionStore
import io.vertx.json.schema.SchemaParser
import org.pf4j.PluginWrapper
import org.springframework.context.annotation.AnnotationConfigApplicationContext

class RouterProvider private constructor(
vertx: Vertx,
applicationContext: AnnotationConfigApplicationContext,
schemaParser: SchemaParser,
configManager: ConfigManager
configManager: ConfigManager,
pluginManager: PluginManager
) {
companion object {
fun create(
vertx: Vertx,
applicationContext: AnnotationConfigApplicationContext,
schemaParser: SchemaParser,
configManager: ConfigManager
configManager: ConfigManager,
pluginManager: PluginManager
) =
RouterProvider(vertx, applicationContext, schemaParser, configManager)
RouterProvider(vertx, applicationContext, schemaParser, configManager, pluginManager)

private var isInitialized = false

Expand Down Expand Up @@ -62,9 +67,14 @@ class RouterProvider private constructor(
init {
val routerConfig = configManager.getConfig().getJsonObject("router")

val beans = applicationContext.getBeansWithAnnotation(Endpoint::class.java)
val routeList = mutableListOf<Route>()

val routeList = beans.map { it.value as Route }.toMutableList()
routeList.addAll(applicationContext.getBeansWithAnnotation(Endpoint::class.java).map { it.value as Route })
routeList.addAll(pluginManager.plugins.map {
((it as PluginWrapper).plugin as ParsekPlugin).pluginBeanContext.getBeansWithAnnotation(
Endpoint::class.java
)
}.flatMap { it.values }.map { it as Route })

val routerEventHandlers = PluginEventManager.getParsekEventListeners<RouterEventListener>()

Expand Down

0 comments on commit 865cbc6

Please sign in to comment.