diff --git a/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/AgentRegisterFactory.java b/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/AgentRegisterFactory.java index 445c9b76..181b5ba3 100644 --- a/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/AgentRegisterFactory.java +++ b/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/AgentRegisterFactory.java @@ -5,6 +5,7 @@ import work.slhaf.partner.api.agent.factory.capability.CapabilityCheckFactory; import work.slhaf.partner.api.agent.factory.capability.CapabilityInjectFactory; import work.slhaf.partner.api.agent.factory.capability.CapabilityRegisterFactory; import work.slhaf.partner.api.agent.factory.component.ComponentAnnotationValidatorFactory; +import work.slhaf.partner.api.agent.factory.component.ComponentInjectorFactory; import work.slhaf.partner.api.agent.factory.component.ComponentRegisterFactory; import work.slhaf.partner.api.agent.factory.component.ModuleInitHookExecuteFactory; import work.slhaf.partner.api.agent.factory.config.ConfigLoaderFactory; @@ -43,7 +44,9 @@ public class AgentRegisterFactory { new ComponentAnnotationValidatorFactory().execute(registerContext); //2. 收集所有的 AgentComponent 实例 new ComponentRegisterFactory().execute(registerContext); - //3. 加载检查Capability层内容后进行能力层的内容注册 + //3. 对模块与额外组件进行模块依赖注入 + new ComponentInjectorFactory().execute(registerContext); + //4. 加载检查Capability层内容后进行能力层的内容注册 new CapabilityCheckFactory().execute(registerContext); new CapabilityRegisterFactory().execute(registerContext); //. 先一步注入Capability,避免因前hook逻辑存在针对能力的引用而报错 diff --git a/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/component/ComponentInjectorFactory.kt b/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/component/ComponentInjectorFactory.kt new file mode 100644 index 00000000..d18953bd --- /dev/null +++ b/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/component/ComponentInjectorFactory.kt @@ -0,0 +1,90 @@ +package work.slhaf.partner.api.agent.factory.component + +import work.slhaf.partner.api.agent.factory.AgentBaseFactory +import work.slhaf.partner.api.agent.factory.component.annotation.InjectModule +import work.slhaf.partner.api.agent.factory.component.exception.ModuleInstanceGenerateFailedException +import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext +import work.slhaf.partner.api.agent.factory.context.ModuleContextData +import java.lang.reflect.Field +import java.lang.reflect.Modifier + +class ComponentInjectorFactory : AgentBaseFactory() { + override fun execute(context: AgentRegisterContext) { + val agentContext = context.agentContext + val moduleContextList = agentContext.modules.values.toList() + + val runningModules = moduleContextList + .filterIsInstance>() + val subModules = moduleContextList + .filterIsInstance>() + val standaloneModules = moduleContextList + .filterIsInstance>() + + val subInstances = subModules.map { it.instance } + val standaloneInstances = standaloneModules.map { it.instance } + + val providersForRunning = subInstances + standaloneInstances + val providersForAdditional = subInstances + standaloneInstances + + runningModules.forEach { running -> + injectIntoTarget(running.instance, providersForRunning) + subModules.forEach { it.injectTarget.add(running.instance) } + standaloneModules.forEach { it.injectTarget.add(running.instance) } + } + + standaloneModules.forEach { standalone -> + injectIntoTarget(standalone.instance, subInstances) + subModules.forEach { it.injectTarget.add(standalone.instance) } + } + + agentContext.additionalComponents.forEach { additional -> + injectIntoTarget(additional, providersForAdditional) + } + } + + private fun injectIntoTarget( + target: Any, + providers: List + ) { + collectInjectFields(target::class.java).forEach { field -> + val value = resolveInjectValue(field, providers, target::class.java) + try { + field.isAccessible = true + field.set(target, value) + } catch (e: IllegalAccessException) { + throw ModuleInstanceGenerateFailedException( + "模块注入失败: ${target::class.java.name}#${field.name}", + e + ) + } + } + } + + private fun resolveInjectValue(field: Field, providers: List, targetClass: Class<*>): Any { + val matched = providers.filter { field.type.isAssignableFrom(it::class.java) } + if (matched.isEmpty()) { + throw ModuleInstanceGenerateFailedException( + "模块注入失败, 未找到可注入实例: ${targetClass.name}#${field.name} -> ${field.type.name}" + ) + } + if (matched.size > 1) { + throw ModuleInstanceGenerateFailedException( + "模块注入失败, 存在多个可注入实例: ${targetClass.name}#${field.name} -> ${field.type.name}" + ) + } + return matched.first() + } + + private fun collectInjectFields(clazz: Class<*>): List { + val fields = mutableListOf() + var current: Class<*>? = clazz + while (current != null && current != Any::class.java) { + current.declaredFields + .filter { it.isAnnotationPresent(InjectModule::class.java) } + .filter { !Modifier.isStatic(it.modifiers) } + .forEach { fields.add(it) } + current = current.superclass + } + return fields + } +}