From fd9b376afaf2ff8fbe7446e80499e40d60b93f2d Mon Sep 17 00:00:00 2001 From: slhafzjw Date: Mon, 23 Feb 2026 21:41:38 +0800 Subject: [PATCH] refactor(framework): replace `CapabilityCheckFactory` with Kotlin `CapabilityAnnotationValidatorFactory` and update capability validation flow --- .../agent/factory/AgentRegisterFactory.java | 4 +- .../CapabilityAnnotationValidatorFactory.kt | 124 ++++++++ .../capability/CapabilityCheckFactory.java | 270 ------------------ 3 files changed, 126 insertions(+), 272 deletions(-) create mode 100644 Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/capability/CapabilityAnnotationValidatorFactory.kt delete mode 100644 Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/capability/CapabilityCheckFactory.java 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 181b5ba3..6047e4c4 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 @@ -1,7 +1,7 @@ package work.slhaf.partner.api.agent.factory; import org.reflections.util.ClasspathHelper; -import work.slhaf.partner.api.agent.factory.capability.CapabilityCheckFactory; +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.CapabilityRegisterFactory; import work.slhaf.partner.api.agent.factory.component.ComponentAnnotationValidatorFactory; @@ -47,7 +47,7 @@ public class AgentRegisterFactory { //3. 对模块与额外组件进行模块依赖注入 new ComponentInjectorFactory().execute(registerContext); //4. 加载检查Capability层内容后进行能力层的内容注册 - new CapabilityCheckFactory().execute(registerContext); + new CapabilityAnnotationValidatorFactory().execute(registerContext); new CapabilityRegisterFactory().execute(registerContext); //. 先一步注入Capability,避免因前hook逻辑存在针对能力的引用而报错 new CapabilityInjectFactory().execute(registerContext); diff --git a/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/capability/CapabilityAnnotationValidatorFactory.kt b/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/capability/CapabilityAnnotationValidatorFactory.kt new file mode 100644 index 00000000..f1e5e582 --- /dev/null +++ b/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/capability/CapabilityAnnotationValidatorFactory.kt @@ -0,0 +1,124 @@ +package work.slhaf.partner.api.agent.factory.capability + +import cn.hutool.core.util.ClassUtil +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.CapabilityCore +import work.slhaf.partner.api.agent.factory.capability.annotation.CapabilityMethod +import work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapability +import work.slhaf.partner.api.agent.factory.capability.exception.DuplicateCapabilityException +import work.slhaf.partner.api.agent.factory.capability.exception.UnMatchedCapabilityException +import work.slhaf.partner.api.agent.factory.capability.exception.UnMatchedCapabilityMethodException +import work.slhaf.partner.api.agent.factory.component.annotation.AgentComponent +import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext +import work.slhaf.partner.api.agent.util.AgentUtil.isAssignableFromAnnotation +import work.slhaf.partner.api.agent.util.AgentUtil.methodSignature + +class CapabilityAnnotationValidatorFactory : AgentBaseFactory() { + override fun execute(context: AgentRegisterContext) { + val reflections = context.reflections + val cores = loadCores(reflections) + val capabilities = loadCapabilities(reflections) + + checkCapabilityUniqueByValue(capabilities) + checkCapabilityMethodLocation(reflections) + checkCapabilityMethodsImplementedUniquely(cores, capabilities) + checkInjectCapability(reflections) + } + + private fun loadCores(reflections: Reflections): Set> { + return reflections.getTypesAnnotatedWith(CapabilityCore::class.java) + .filter { ClassUtil.isNormalClass(it) } + .toSet() + } + + private fun loadCapabilities(reflections: Reflections): Set> { + return reflections.getTypesAnnotatedWith(Capability::class.java).toSet() + } + + /** + * 规则1: @Capability 按 value 唯一 + */ + private fun checkCapabilityUniqueByValue(capabilities: Set>) { + val capabilityByValue = LinkedHashMap>() + capabilities.forEach { capability -> + val value = capability.getAnnotation(Capability::class.java).value + val existed = capabilityByValue.putIfAbsent(value, capability) + if (existed != null) { + throw DuplicateCapabilityException("Capability 注册异常: 重复的Capability接口: $value") + } + } + } + + /** + * 规则3.1: @CapabilityMethod 仅能用于 @CapabilityCore 类 + */ + private fun checkCapabilityMethodLocation(reflections: Reflections) { + reflections.getMethodsAnnotatedWith(CapabilityMethod::class.java) + .forEach { method -> + val declaringClass = method.declaringClass + if (!declaringClass.isAnnotationPresent(CapabilityCore::class.java)) { + throw UnMatchedCapabilityException( + "@CapabilityMethod 仅能用于 @CapabilityCore 所标注类中: " + + "${declaringClass.name}#${method.name}" + ) + } + } + } + + /** + * 规则3.2: + * @Capability 接口方法,必须在对应 value 的 @CapabilityCore 集合中存在唯一实现 + */ + private fun checkCapabilityMethodsImplementedUniquely( + cores: Set>, + capabilities: Set> + ) { + val coreMethodsByValue = LinkedHashMap>>() + cores.forEach { core -> + val value = core.getAnnotation(CapabilityCore::class.java).value + val signatureMap = coreMethodsByValue.computeIfAbsent(value) { LinkedHashMap() } + core.methods + .filter { it.isAnnotationPresent(CapabilityMethod::class.java) } + .forEach { method -> + val signature = methodSignature(method) + val implementors = signatureMap.computeIfAbsent(signature) { mutableListOf() } + implementors.add(core.name) + } + } + + capabilities.forEach { capability -> + val capabilityValue = capability.getAnnotation(Capability::class.java).value + val signatureMap = coreMethodsByValue[capabilityValue].orEmpty() + capability.methods.forEach { method -> + val signature = methodSignature(method) + val implementors = signatureMap[signature].orEmpty() + if (implementors.isEmpty()) { + throw UnMatchedCapabilityMethodException( + "Capability方法缺少实现: $capabilityValue.$signature" + ) + } + if (implementors.size > 1) { + throw UnMatchedCapabilityMethodException( + "Capability方法存在多个实现: $capabilityValue.$signature -> ${implementors.joinToString(", ")}" + ) + } + } + } + } + + /** + * 维持现有校验: @InjectCapability 仅能用于 AgentComponent + */ + private fun checkInjectCapability(reflections: Reflections) { + reflections.getFieldsAnnotatedWith(InjectCapability::class.java).forEach { field -> + val declaringClass = field.declaringClass + if (!isAssignableFromAnnotation(declaringClass, AgentComponent::class.java)) { + throw UnMatchedCapabilityException( + "InjectCapability 注解只能用于 AgentComponent 注解所在类,检查该类是否使用了@CapabilityHolder注解或者受其标注的注解或父类: $declaringClass" + ) + } + } + } +} diff --git a/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/capability/CapabilityCheckFactory.java b/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/capability/CapabilityCheckFactory.java deleted file mode 100644 index 80af87d4..00000000 --- a/Partner-Framework/src/main/java/work/slhaf/partner/api/agent/factory/capability/CapabilityCheckFactory.java +++ /dev/null @@ -1,270 +0,0 @@ -package work.slhaf.partner.api.agent.factory.capability; - -import cn.hutool.core.util.ClassUtil; -import org.reflections.Reflections; -import work.slhaf.partner.api.agent.factory.AgentBaseFactory; -import work.slhaf.partner.api.agent.factory.capability.annotation.*; -import work.slhaf.partner.api.agent.factory.capability.exception.*; -import work.slhaf.partner.api.agent.factory.component.annotation.AgentComponent; -import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext; -import work.slhaf.partner.api.agent.factory.context.CapabilityFactoryContext; -import work.slhaf.partner.api.agent.util.AgentUtil; - -import java.lang.reflect.Method; -import java.util.*; -import java.util.stream.Collectors; - -import static work.slhaf.partner.api.agent.util.AgentUtil.isAssignableFromAnnotation; -import static work.slhaf.partner.api.agent.util.AgentUtil.methodSignature; - -/** - *

Agent启动流程 4

- * - *

负责通过反射收集 {@link Capability} 和 {@link CapabilityCore} 注解所在类,并判断是否存在被错误忽略的方法

- * - *
    - *
  1. - *

    {@link CapabilityCheckFactory#loadCoresAndCapabilities()}

    - * 通过反射收集 {@link Capability} 和 {@link CapabilityCore} 注解所在类为对应集合 - *
  2. - *
  3. - *

    {@link CapabilityCheckFactory#checkCountAndCapabilities()}

    - * 检测 {@link Capability} 与 {@link CapabilityCore} 的数量、对应的能力是否相等。每一个core都将对应一个capability,并通过value属性进行匹配 - *
  4. - *
  5. - *

    {@link CapabilityCheckFactory#checkCapabilityMethods()}

    - * 检测在 {@link Capability} 与 {@link CapabilityCore} 中是否存在对方尚未实现/注册的方法 - *
  6. - *
  7. - *

    {@link CapabilityCheckFactory#checkCoordinatedMethods()}

    - * 检查是否包含协调方法({@link ToCoordinated}),如果存在,则进一步检查在 {@link CoordinateManager} 所注类中是否有提供对应的实现 - *
  8. - *
  9. - *

    {@link CapabilityCheckFactory#checkInjectCapability()}

    - * 检查 {@link InjectCapability} 注解是否只用在 {@link AgentComponent} 所标识类的字段上。{@link AgentRunningModule} 与 {@link AgentSubModule} 已经被 {@link AgentComponent} 标注 - *
  10. - *
- * - *

下一步流程请参阅{@link CapabilityRegisterFactory}

- */ -public class CapabilityCheckFactory extends AgentBaseFactory { - - private Reflections reflections; - private Set> cores; - private Set> capabilities; - - - @Override - protected void setVariables(AgentRegisterContext context) { - CapabilityFactoryContext factoryContext = context.getCapabilityFactoryContext(); - reflections = context.getReflections(); - cores = factoryContext.getCores(); - capabilities = factoryContext.getCapabilities(); - } - - @Override - protected void run() { - loadCoresAndCapabilities(); - checkCountAndCapabilities(); - checkCapabilityMethods(); - checkCoordinatedMethods(); - checkCoordinatedManager(); - checkInjectCapability(); - } - - private void checkCoordinatedManager() { - reflections.getTypesAnnotatedWith(CoordinateManager.class) - .stream() - .filter(ClassUtil::isNormalClass) - .forEach(managerClass -> { - try { - if (!managerClass.getDeclaredConstructor().canAccess(null)) { - throw new CapabilityCheckFailedException("CoordinateManager 所注类的无参构造方法未公开!"); - } - } catch (NoSuchMethodException e) { - throw new CapabilityCheckFailedException("CoordinateManager 所注类缺少无参构造方法!"); - } - }); - } - - private void loadCoresAndCapabilities() { - cores.addAll(reflections.getTypesAnnotatedWith(CapabilityCore.class)); - capabilities.addAll(reflections.getTypesAnnotatedWith(Capability.class)); - } - - /** - * 检查@InjectCapability注解是否只用在@AgentComponent所标识类的字段上 - */ - private void checkInjectCapability() { - reflections.getFieldsAnnotatedWith(InjectCapability.class).forEach(field -> { - Class declaringClass = field.getDeclaringClass(); - if (!isAssignableFromAnnotation(declaringClass, AgentComponent.class)) { - throw new UnMatchedCapabilityException("InjectCapability 注解只能用于 AgentComponent 注解所在类,检查该类是否使用了@CapabilityHolder注解或者受其标注的注解或父类: " + declaringClass); - } - }); - } - - /** - * 检查是否包含协调方法,如果存在,则进一步检查是否存在@CoordinateManager提供对应的实现 - */ - private void checkCoordinatedMethods() { - //检查各个capability中是否含有ToCoordinated注解 - //如果含有,则需要查找AbstractCognationManager的子类,看这里是否有对应的Coordinated注解所在方法 - Set methodsToCoordinated = capabilities.stream() - .flatMap(capability -> Arrays.stream(capability.getDeclaredMethods())) - .filter(method -> method.isAnnotationPresent(ToCoordinated.class)) - .map(method -> { - String capabilityValue = method.getDeclaringClass().getAnnotation(Capability.class).value(); - return capabilityValue + "." + methodSignature(method); - }) - .collect(Collectors.toSet()); - if (!methodsToCoordinated.isEmpty()) { - Set> subTypesOfAbsCM = reflections.getTypesAnnotatedWith(CoordinateManager.class); - Set methodsCoordinated = getMethodsCoordinated(subTypesOfAbsCM); - if (!methodsCoordinated.equals(methodsToCoordinated)) { - // 找出缺少的协调方法 - Set missingMethods = new HashSet<>(methodsToCoordinated); - missingMethods.removeAll(methodsCoordinated); - - // 找出多余的协调方法 - Set extraMethods = new HashSet<>(methodsCoordinated); - extraMethods.removeAll(methodsToCoordinated); - - // 抛出异常或记录错误 - if (!missingMethods.isEmpty()) { - throw new UnMatchedCoordinatedMethodException("缺少协调方法: " + String.join(", ", missingMethods)); - } - if (!extraMethods.isEmpty()) { - throw new UnMatchedCoordinatedMethodException("发现多余的协调方法: " + String.join(", ", extraMethods)); - } - } - } - } - - private Set getMethodsCoordinated(Set> classes) { - Set methodsCoordinated = new HashSet<>(); - for (Class cm : classes) { - Method[] methods = cm.getMethods(); - for (Method method : methods) { - if (method.isAnnotationPresent(Coordinated.class)) { - methodsCoordinated.add(method.getAnnotation(Coordinated.class).capability() + "." + methodSignature(method)); - } - } - } - return methodsCoordinated; - } - - /** - * 查看在Capability在对应的CapabilityCore中存在尚未实现的方法 - */ - private void checkCapabilityMethods() { - HashMap> capabilitiesMethods = getCapabilityMethods(capabilities); - StringBuilder sb = new StringBuilder(); - for (Class core : cores) { - List methodsWithAnnotation = Arrays.stream(core.getMethods()) - .filter(method -> method.isAnnotationPresent(CapabilityMethod.class)) - .toList(); - List capabilityMethods = capabilitiesMethods.get(core.getAnnotation(CapabilityCore.class).value()); - LackRecord lackRecord = checkMethodsMatched(methodsWithAnnotation, capabilityMethods); - if (lackRecord.hasNotEmptyRecord()) { - sb.append(lackRecord.toLackErrorMsg(core.getAnnotation(CapabilityCore.class).value())); - } - } - if (!sb.isEmpty()) { - throw new UnMatchedCapabilityMethodException(sb.toString()); - } - } - - private LackRecord checkMethodsMatched(List methodsWithAnnotation, List capabilityMethods) { - Set collectedMethodsWithAnnotation = methodsWithAnnotation.stream() - .filter(method -> !method.isAnnotationPresent(ToCoordinated.class)) - .map(AgentUtil::methodSignature) - .collect(Collectors.toSet()); - Set collectedCapabilityMethods = capabilityMethods.stream() - .filter(method -> !method.isAnnotationPresent(ToCoordinated.class)) - .map(AgentUtil::methodSignature) - .collect(Collectors.toSet()); - return checkMethodsMatched(collectedMethodsWithAnnotation, collectedCapabilityMethods); - } - - private LackRecord checkMethodsMatched(Set collectedMethodsWithAnnotation, Set collectedCapabilityMethods) { - List coreLack = new ArrayList<>(); - List capLack = new ArrayList<>(); - // 找出 core 中多余的方法 - for (String coreSig : collectedMethodsWithAnnotation) { - if (!collectedCapabilityMethods.contains(coreSig)) { - capLack.add(coreSig); - } - } - // 找出 capability 中多余的方法 - for (String capSig : collectedCapabilityMethods) { - if (!collectedMethodsWithAnnotation.contains(capSig)) { - coreLack.add(capSig); - } - } - return new LackRecord(coreLack, capLack); - - } - - - private HashMap> getCapabilityMethods(Set> capabilities) { - HashMap> capabilityMethods = new HashMap<>(); - capabilities.forEach(capability -> { - capabilityMethods.put(capability.getAnnotation(Capability.class).value(), Arrays.stream(capability.getMethods()).toList()); - }); - return capabilityMethods; - } - - /** - * 检查CapabilityCapabilityCore的数量和标识是否匹配 - */ - private void checkCountAndCapabilities() { - if (cores.size() != capabilities.size()) { - throw new UnMatchedCapabilityException("Capability 注册异常: 已存在的CapabilityCore与Capability数量不匹配!"); - } - if (!checkValuesMatched(cores, capabilities)) { - throw new UnMatchedCapabilityException("Capability 注册异常: 已存在的CapabilityCore与Capability不匹配!"); - } - } - - private boolean checkValuesMatched(Set> cores, Set> capabilities) { - Set coresValues = new HashSet<>(); - Set capabilitiesValues = new HashSet<>(); - for (Class core : cores) { - CapabilityCore annotation = core.getAnnotation(CapabilityCore.class); - if (annotation != null) { - if (coresValues.contains(annotation.value())) { - throw new DuplicateCapabilityException(String.format("Capability 注册异常: 重复的Capability核心: %s", annotation.value())); - } - coresValues.add(annotation.value()); - } - } - for (Class capability : capabilities) { - Capability annotation = capability.getAnnotation(Capability.class); - if (annotation != null) { - if (capabilitiesValues.contains(annotation.value())) { - throw new DuplicateCapabilityException(String.format("Capability 注册异常: 重复的Capability接口: %s", annotation.value())); - } - capabilitiesValues.add(annotation.value()); - } - } - return coresValues.equals(capabilitiesValues); - } - - record LackRecord(List coreLack, List capLack) { - public boolean hasNotEmptyRecord() { - return !coreLack.isEmpty() || !capLack.isEmpty(); - } - - public String toLackErrorMsg(String capabilityName) { - StringBuilder sb = new StringBuilder("\n").append(capabilityName).append("\n"); - if (!coreLack.isEmpty()) { - sb.append("缺少Core方法:").append("\n").append(coreLack).append("\n"); - } - if (!capLack.isEmpty()) { - sb.append("缺少Capability方法:").append("\n").append(capLack).append("\n"); - } - return sb.toString(); - } - } -}