mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 08:43:02 +08:00
refactor(framework): replace ModuleInitHookExecuteFactory with Kotlin ComponentInitHookExecuteFactory and drive @Init execution from validated component context
This commit is contained in:
@@ -5,9 +5,9 @@ import work.slhaf.partner.api.agent.factory.capability.CapabilityAnnotationValid
|
||||
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.component.ComponentAnnotationValidatorFactory;
|
||||
import work.slhaf.partner.api.agent.factory.component.ComponentInitHookExecuteFactory;
|
||||
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;
|
||||
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
|
||||
import work.slhaf.partner.api.agent.factory.exception.ExternalModuleLoadFailedException;
|
||||
@@ -52,8 +52,8 @@ public class AgentRegisterFactory {
|
||||
new CapabilityRegisterFactory().execute(registerContext);
|
||||
//6. 将 Capability 实例注入至各个 AgentComponent 中
|
||||
new CapabilityInjectorFactory().execute(registerContext);
|
||||
//. 执行模块PreHook逻辑
|
||||
new ModuleInitHookExecuteFactory().execute(registerContext);
|
||||
//7. 执行模块PreHook逻辑
|
||||
new ComponentInitHookExecuteFactory().execute(registerContext);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ import work.slhaf.partner.api.agent.util.AgentUtil
|
||||
class ComponentAnnotationValidatorFactory : AgentBaseFactory() {
|
||||
override fun execute(context: AgentRegisterContext) {
|
||||
val reflections = context.reflections
|
||||
val componentFactoryContext = context.componentFactoryContext
|
||||
componentFactoryContext.initMethodsByDeclaringType.clear()
|
||||
|
||||
reflections.getMethodsAnnotatedWith(Init::class.java)
|
||||
.forEach { method ->
|
||||
@@ -22,6 +24,10 @@ class ComponentAnnotationValidatorFactory : AgentBaseFactory() {
|
||||
"${declaringClass.name}#${method.name}"
|
||||
)
|
||||
}
|
||||
val methods = componentFactoryContext
|
||||
.initMethodsByDeclaringType
|
||||
.getOrPut(declaringClass) { LinkedHashSet() }
|
||||
methods.add(method)
|
||||
}
|
||||
|
||||
reflections.getFieldsAnnotatedWith(InjectModule::class.java)
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
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.Init
|
||||
import work.slhaf.partner.api.agent.factory.component.exception.ModuleInitHookExecuteFailedException
|
||||
import work.slhaf.partner.api.agent.factory.context.AgentContext
|
||||
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext
|
||||
import work.slhaf.partner.api.agent.util.AgentUtil.methodSignature
|
||||
import java.lang.reflect.Method
|
||||
|
||||
class ComponentInitHookExecuteFactory : AgentBaseFactory() {
|
||||
override fun execute(context: AgentRegisterContext) {
|
||||
val initMethodsByDeclaringType = context.componentFactoryContext.initMethodsByDeclaringType
|
||||
val targets = buildTargets(context.agentContext)
|
||||
|
||||
targets.forEach { target ->
|
||||
val initMethods = collectInitMethods(target::class.java, initMethodsByDeclaringType)
|
||||
executeInitMethods(target, initMethods)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildTargets(agentContext: AgentContext): List<Any> {
|
||||
val moduleInstances = agentContext.modules.values.map { it.instance }
|
||||
return moduleInstances + agentContext.additionalComponents
|
||||
}
|
||||
|
||||
private fun collectInitMethods(
|
||||
targetType: Class<*>,
|
||||
initMethodsByDeclaringType: Map<Class<*>, Set<Method>>
|
||||
): List<Method> {
|
||||
val methods = LinkedHashSet<Method>()
|
||||
var current: Class<*>? = targetType
|
||||
while (current != null && current != Any::class.java) {
|
||||
initMethodsByDeclaringType[current]?.forEach { methods.add(it) }
|
||||
current = current.superclass
|
||||
}
|
||||
return methods
|
||||
.sortedBy { it.getAnnotation(Init::class.java)?.order ?: 0 }
|
||||
}
|
||||
|
||||
private fun executeInitMethods(target: Any, initMethods: List<Method>) {
|
||||
initMethods.forEach { method ->
|
||||
try {
|
||||
if (method.parameterCount > 0) {
|
||||
throw ModuleInitHookExecuteFailedException(
|
||||
"Init方法不支持参数: ${target::class.java.name}#${methodSignature(method)}"
|
||||
)
|
||||
}
|
||||
method.isAccessible = true
|
||||
method.invoke(target)
|
||||
} catch (e: ModuleInitHookExecuteFailedException) {
|
||||
throw e
|
||||
} catch (e: Exception) {
|
||||
throw ModuleInitHookExecuteFailedException(
|
||||
"模块的init hook方法执行失败! 模块: ${target::class.java.simpleName} 方法签名: ${
|
||||
methodSignature(
|
||||
method
|
||||
)
|
||||
}",
|
||||
e
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
package work.slhaf.partner.api.agent.factory.component;
|
||||
|
||||
import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
|
||||
import work.slhaf.partner.api.agent.factory.AgentRegisterFactory;
|
||||
import work.slhaf.partner.api.agent.factory.component.abstracts.AbstractAgentModule;
|
||||
import work.slhaf.partner.api.agent.factory.component.annotation.Init;
|
||||
import work.slhaf.partner.api.agent.factory.component.exception.ModuleInitHookExecuteFailedException;
|
||||
import work.slhaf.partner.api.agent.factory.component.pojo.BaseMetaModule;
|
||||
import work.slhaf.partner.api.agent.factory.component.pojo.MetaMethod;
|
||||
import work.slhaf.partner.api.agent.factory.component.pojo.MetaModule;
|
||||
import work.slhaf.partner.api.agent.factory.component.pojo.MetaSubModule;
|
||||
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
|
||||
import work.slhaf.partner.api.agent.util.AgentUtil;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static work.slhaf.partner.api.agent.util.AgentUtil.collectExtendedClasses;
|
||||
import static work.slhaf.partner.api.agent.util.AgentUtil.methodSignature;
|
||||
|
||||
/**
|
||||
* <h2>Agent启动流程 7</h2>
|
||||
*
|
||||
* <p>负责执行初始化hook逻辑,即 {@link Init} 注解所在方法</p>
|
||||
*
|
||||
* <ol>
|
||||
* <li>
|
||||
* <p>{@link ModuleInitHookExecuteFactory#collectInitHookMethods(Class, Class)}</p>
|
||||
* 分别遍历前置模块拿到的模块列表({@link ModuleInitHookExecuteFactory#moduleList}, {@link ModuleInitHookExecuteFactory#subModuleList}),通过 {@link AgentUtil#collectExtendedClasses(Class, Class)} 收集到当前模块类的继承链上的所有类后,收集其所有带有 {@link Init} 注解的方法
|
||||
* </li>
|
||||
* <li>
|
||||
* <p>{@link ModuleInitHookExecuteFactory#proceedInitMethods(BaseMetaModule, List)}</p>
|
||||
* 收集好初始化方法后,将通过反射执行该方法,所用实例即为前置模块中收集到的执行模块与子模块的 {@link MetaModule} 与 {@link MetaSubModule} 内容
|
||||
* </li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>Agent启动流程到此进行完毕。整个工厂执行链中均为针对 {@link AgentRegisterContext} 进行的操作,在 {@link AgentRegisterFactory} 中,将进行最终处理以及将必要内容进行传递。</p>
|
||||
*/
|
||||
public class ModuleInitHookExecuteFactory extends AgentBaseFactory {
|
||||
|
||||
private List<MetaModule> moduleList;
|
||||
private List<MetaSubModule> subModuleList;
|
||||
|
||||
@Override
|
||||
protected void setVariables(AgentRegisterContext context) {
|
||||
ModuleFactoryContext factoryContext = context.getModuleFactoryContext();
|
||||
moduleList = factoryContext.getAgentModuleList();
|
||||
subModuleList = factoryContext.getAgentSubModuleList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
//遍历模块列表,并向上查找@Init注解
|
||||
for (MetaSubModule metaSubModule : subModuleList) {
|
||||
List<MetaMethod> initHookMethods = collectInitHookMethods(metaSubModule.getClazz(), AbstractAgentRunningModule.class);
|
||||
proceedInitMethods(metaSubModule, initHookMethods);
|
||||
}
|
||||
|
||||
for (MetaModule metaModule : moduleList) {
|
||||
List<MetaMethod> initHookMethods = collectInitHookMethods(metaModule.getClazz(), AbstractAgentSubModule.class);
|
||||
proceedInitMethods(metaModule, initHookMethods);
|
||||
}
|
||||
}
|
||||
|
||||
private void proceedInitMethods(BaseMetaModule metaModule, List<MetaMethod> initHookMethods) {
|
||||
for (MetaMethod metaMethod : initHookMethods) {
|
||||
try {
|
||||
metaMethod.getMethod().invoke(metaModule.getInstance());
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new ModuleInitHookExecuteFailedException("模块的init hook方法执行失败! 模块: " + metaModule.getClazz().getSimpleName() + " 方法签名: " + methodSignature(metaMethod.getMethod()), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<MetaMethod> collectInitHookMethods(Class<?> clazz, Class<? extends AbstractAgentModule> target) {
|
||||
Set<Class<?>> classes = collectExtendedClasses(clazz, target);
|
||||
return classes.stream()
|
||||
.map(Class::getDeclaredMethods)
|
||||
.flatMap(Arrays::stream)
|
||||
.filter(method -> method.isAnnotationPresent(Init.class))
|
||||
.map(method -> {
|
||||
MetaMethod metaMethod = new MetaMethod();
|
||||
metaMethod.setMethod(method);
|
||||
metaMethod.setOrder(method.getAnnotation(Init.class).order());
|
||||
return metaMethod;
|
||||
})
|
||||
.sorted(Comparator.comparing(MetaMethod::getOrder))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ class AgentRegisterContext(urls: List<URL>) {
|
||||
|
||||
val configFactoryContext: ConfigFactoryContext = ConfigFactoryContext()
|
||||
val capabilityFactoryContext: CapabilityFactoryContext = CapabilityFactoryContext()
|
||||
val componentFactoryContext: ComponentFactoryContext = ComponentFactoryContext()
|
||||
val agentContext: AgentContext = AgentContext
|
||||
}
|
||||
|
||||
@@ -33,3 +34,7 @@ class CapabilityFactoryContext {
|
||||
val capabilities: MutableSet<Class<*>> = LinkedHashSet()
|
||||
val methods: MutableSet<Method> = LinkedHashSet()
|
||||
}
|
||||
|
||||
class ComponentFactoryContext {
|
||||
val initMethodsByDeclaringType: MutableMap<Class<*>, MutableSet<Method>> = LinkedHashMap()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user