refactor(framework): migrate capability injection to Kotlin CapabilityInjectorFactory and inject capability instances directly into components

This commit is contained in:
2026-02-23 22:59:47 +08:00
parent 7ee698768c
commit 1b164cedf1
3 changed files with 83 additions and 89 deletions

View File

@@ -2,7 +2,7 @@ package work.slhaf.partner.api.agent.factory;
import org.reflections.util.ClasspathHelper; import org.reflections.util.ClasspathHelper;
import work.slhaf.partner.api.agent.factory.capability.CapabilityAnnotationValidatorFactory; import work.slhaf.partner.api.agent.factory.capability.CapabilityAnnotationValidatorFactory;
import work.slhaf.partner.api.agent.factory.capability.CapabilityInjectFactory; import work.slhaf.partner.api.agent.factory.capability.CapabilityInjectorFactory;
import work.slhaf.partner.api.agent.factory.capability.CapabilityRegisterFactory; 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.ComponentAnnotationValidatorFactory;
import work.slhaf.partner.api.agent.factory.component.ComponentInjectorFactory; import work.slhaf.partner.api.agent.factory.component.ComponentInjectorFactory;
@@ -50,8 +50,8 @@ public class AgentRegisterFactory {
new CapabilityAnnotationValidatorFactory().execute(registerContext); new CapabilityAnnotationValidatorFactory().execute(registerContext);
//5. 根据 Capability 相关的扫描结果构造 Capability 实例 //5. 根据 Capability 相关的扫描结果构造 Capability 实例
new CapabilityRegisterFactory().execute(registerContext); new CapabilityRegisterFactory().execute(registerContext);
//. 先一步注入Capability,避免因前hook逻辑存在针对能力的引用而报错 //6. Capability 实例注入至各个 AgentComponent 中
new CapabilityInjectFactory().execute(registerContext); new CapabilityInjectorFactory().execute(registerContext);
//. 执行模块PreHook逻辑 //. 执行模块PreHook逻辑
new ModuleInitHookExecuteFactory().execute(registerContext); new ModuleInitHookExecuteFactory().execute(registerContext);

View File

@@ -1,86 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability;
import org.reflections.Reflections;
import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
import work.slhaf.partner.api.agent.factory.capability.annotation.Capability;
import work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapability;
import work.slhaf.partner.api.agent.factory.capability.annotation.ToCoordinated;
import work.slhaf.partner.api.agent.factory.capability.exception.CapabilityProxySetFailedException;
import work.slhaf.partner.api.agent.factory.component.ModuleInitHookExecuteFactory;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Set;
import java.util.function.Function;
import static work.slhaf.partner.api.agent.util.AgentUtil.methodSignature;
/**
* <h2>Agent启动流程 6</h2>
*
* <p>负责执行 {@link Capability} 的注入逻辑。</p>
*
* <p>实现方式:</p>
* <ol>
* <li>通过动态代理,为 {@link AgentRunningModule} 与 {@link AgentSubModule} 中待注入的
* <b>能力接口</b> 类型(即 {@link Capability} 标注的接口类)生成代理对象。
* </li>
* <li>在代理对象内部,根据调用方法的签名确定路由,将调用转发至对应的具体函数。
* </li>
* <li>通过此机制,实现了 {@link Capability} 单一语义层面上普通方法与协调方法的统一入口。
* </li>
* </ol>
*
* <p>下一步流程请参阅 {@link ModuleInitHookExecuteFactory}</p>
*/
public class CapabilityInjectFactory extends AgentBaseFactory {
private Reflections reflections;
private HashMap<String, Function<Object[], Object>> coordinatedMethodsRouterTable;
private HashMap<String, Function<Object[], Object>> methodsRouterTable;
private HashMap<Class<?>, Object> capabilityHolderInstances;
@Override
protected void setVariables(AgentRegisterContext context) {
CapabilityFactoryContext factoryContext = context.getCapabilityFactoryContext();
reflections = context.getReflections();
coordinatedMethodsRouterTable = factoryContext.getCoordinatedMethodsRouterTable();
methodsRouterTable = factoryContext.getMethodsRouterTable();
capabilityHolderInstances = factoryContext.getCapabilityHolderInstances();
}
@Override
protected void run() {
//获取现有的`@InjectCapability`注解所在字段,并获取对应的类,通过动态代理注入对象
Set<Field> fields = reflections.getFieldsAnnotatedWith(InjectCapability.class);
//在动态代理内部,通过函数路由表调用对应的方法
createProxy(fields);
}
private void createProxy(Set<Field> fields) {
try {
for (Field field : fields) {
field.setAccessible(true);
Class<?> fieldType = field.getType();
Object instance = Proxy.newProxyInstance(
fieldType.getClassLoader(),
new Class[]{fieldType},
(proxy, method, objects) -> {
if (method.isAnnotationPresent(ToCoordinated.class)) {
String key = method.getDeclaringClass().getAnnotation(Capability.class).value() + "." + methodSignature(method);
return coordinatedMethodsRouterTable.get(key).apply(objects);
}
String key = fieldType.getAnnotation(Capability.class).value() + "." + methodSignature(method);
return methodsRouterTable.get(key).apply(objects);
}
);
field.set(capabilityHolderInstances.get(field.getDeclaringClass()), instance);
}
} catch (Exception e) {
throw new CapabilityProxySetFailedException("代理设置失败", e);
}
}
}

View File

@@ -0,0 +1,80 @@
package work.slhaf.partner.api.agent.factory.capability
import work.slhaf.partner.api.agent.factory.AgentBaseFactory
import work.slhaf.partner.api.agent.factory.capability.annotation.Capability
import work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapability
import work.slhaf.partner.api.agent.factory.capability.exception.CapabilityProxySetFailedException
import work.slhaf.partner.api.agent.factory.context.AgentContext
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext
import java.lang.reflect.Field
import java.lang.reflect.Modifier
class CapabilityInjectorFactory : AgentBaseFactory() {
override fun execute(context: AgentRegisterContext) {
val agentContext = context.agentContext
val targets = buildTargets(agentContext)
targets.forEach { target ->
injectCapabilities(target, agentContext.capabilities)
}
}
private fun buildTargets(agentContext: AgentContext): List<Any> {
val moduleInstances = agentContext.modules.values.map { it.instance }
return moduleInstances + agentContext.additionalComponents
}
private fun injectCapabilities(
target: Any,
capabilityMap: Map<String, AgentContext.CapabilityImplementation>
) {
collectInjectFields(target::class.java).forEach { field ->
try {
field.isAccessible = true
val value = resolveCapabilityInstance(field, capabilityMap, target::class.java)
field.set(target, value)
} catch (e: CapabilityProxySetFailedException) {
throw e
} catch (e: Exception) {
throw CapabilityProxySetFailedException(
"Capability 注入失败: ${target::class.java.name}#${field.name}",
e
)
}
}
}
private fun resolveCapabilityInstance(
field: Field,
capabilityMap: Map<String, AgentContext.CapabilityImplementation>,
targetClass: Class<*>
): Any {
val capability = field.type.getAnnotation(Capability::class.java)
?: throw CapabilityProxySetFailedException(
"InjectCapability 字段类型未标注 @Capability: ${targetClass.name}#${field.name} -> ${field.type.name}"
)
val capabilityValue = capability.value
val implementation = capabilityMap[capabilityValue] ?: throw CapabilityProxySetFailedException(
"未找到可注入 Capability 实例: ${targetClass.name}#${field.name} -> $capabilityValue"
)
if (!field.type.isAssignableFrom(implementation.instance.javaClass)) {
throw CapabilityProxySetFailedException(
"Capability 实例类型不匹配: ${targetClass.name}#${field.name} -> $capabilityValue"
)
}
return implementation.instance
}
private fun collectInjectFields(clazz: Class<*>): List<Field> {
val fields = mutableListOf<Field>()
var current: Class<*>? = clazz
while (current != null && current != Any::class.java) {
current.declaredFields
.filter { it.isAnnotationPresent(InjectCapability::class.java) }
.filter { !Modifier.isStatic(it.modifiers) }
.forEach { fields.add(it) }
current = current.superclass
}
return fields
}
}