mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 08:43:02 +08:00
继续推进框架中的模块注册机制。
- 完善 ModuleProxyFactory 中的hook逻辑代理实现,从模块类开始,自下而上扫描继承链中每个类的hook方法, 收集完毕并排序后统一实现代理逻辑。 - 从 ModuleFactoryContext 、 ModuleRegisterFactory 中移除了原有的‘先注册hook方法’相关内容。 - 更新 README
This commit is contained in:
@@ -12,7 +12,5 @@ import java.util.Set;
|
||||
@Data
|
||||
public class ModuleFactoryContext {
|
||||
private List<MetaModule> moduleList = new ArrayList<>();
|
||||
private HashMap<Class<?>,Set<MetaMethod>> preHookMethods = new HashMap<>();
|
||||
private HashMap<Class<?>,Set<MetaMethod>> postHookMethods = new HashMap<>();
|
||||
private HashMap<Class<?>,Set<MetaMethod>> initHookMethods = new HashMap<>();
|
||||
}
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
package work.slhaf.partner.api.factory.module;
|
||||
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.implementation.MethodDelegation;
|
||||
import net.bytebuddy.implementation.bind.annotation.*;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
import work.slhaf.partner.api.factory.AgentBaseFactory;
|
||||
import work.slhaf.partner.api.factory.context.AgentRegisterContext;
|
||||
import work.slhaf.partner.api.factory.context.ModuleFactoryContext;
|
||||
import work.slhaf.partner.api.factory.module.annotation.AfterExecute;
|
||||
import work.slhaf.partner.api.factory.module.annotation.BeforeExecute;
|
||||
import work.slhaf.partner.api.factory.module.exception.ModuleInstanceGenerateFailedException;
|
||||
import work.slhaf.partner.api.factory.module.exception.ModuleProxyGenerateFailedException;
|
||||
import work.slhaf.partner.api.factory.module.pojo.MetaMethod;
|
||||
import work.slhaf.partner.api.factory.module.pojo.MetaModule;
|
||||
import work.slhaf.partner.api.flow.abstracts.AgentInteractionModule;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 通过扫描注解<code>@BeforeExecute</code>,获取到各个模块的后hook逻辑并通过动态代理添加到执行逻辑之后
|
||||
@@ -23,20 +27,15 @@ import java.util.concurrent.Callable;
|
||||
public class ModuleProxyFactory extends AgentBaseFactory {
|
||||
|
||||
private List<MetaModule> moduleList;
|
||||
private HashMap<Class<?>, Set<MetaMethod>> postHookMethods;
|
||||
private HashMap<Class<?>, Set<MetaMethod>> preHookMethods;
|
||||
|
||||
@Override
|
||||
protected void setVariables(AgentRegisterContext context) {
|
||||
ModuleFactoryContext factoryContext = context.getModuleFactoryContext();
|
||||
moduleList = factoryContext.getModuleList();
|
||||
postHookMethods = factoryContext.getPostHookMethods();
|
||||
preHookMethods = factoryContext.getPreHookMethods();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
||||
//TODO 填充具体逻辑
|
||||
generateInstances();
|
||||
setHookProxy();
|
||||
}
|
||||
@@ -45,42 +44,115 @@ public class ModuleProxyFactory extends AgentBaseFactory {
|
||||
for (MetaModule module : moduleList) {
|
||||
Class<?> clazz = module.getClazz();
|
||||
try {
|
||||
MethodsListRecord record = getHookMethodsList(clazz);
|
||||
MethodsListRecord record = collectHookMethods(clazz);
|
||||
//生成实例,
|
||||
generateProxiedInstances(record);
|
||||
generateProxiedInstances(record, module);
|
||||
} catch (Exception e) {
|
||||
throw new ModuleProxyGenerateFailedException("创建代理对象失败: " + clazz.getSimpleName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateProxiedInstances(MethodsListRecord record) {
|
||||
|
||||
private void generateProxiedInstances(MethodsListRecord record, MetaModule metaModule) {
|
||||
try {
|
||||
Class<?> clazz = metaModule.getClazz();
|
||||
Class<?> proxyClass = new ByteBuddy()
|
||||
.subclass(clazz)
|
||||
.method(ElementMatchers.isOverriddenFrom(AgentInteractionModule.class))
|
||||
.intercept(MethodDelegation.to(new ModuleProxyInterceptor(record.post, record.pre)))
|
||||
.make()
|
||||
.load(ModuleProxyFactory.class.getClassLoader())
|
||||
.getLoaded();
|
||||
metaModule.setInstance(proxyClass.getConstructor().newInstance());
|
||||
} catch (Exception e) {
|
||||
throw new ModuleProxyGenerateFailedException("模块Hook代理生成失败! 代理失败的模块名: " + metaModule.getClazz().getSimpleName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private MethodsListRecord getHookMethodsList(Class<?> clazz) {
|
||||
private MethodsListRecord collectHookMethods(Class<?> clazz) {
|
||||
List<MetaMethod> post = new ArrayList<>();
|
||||
List<MetaMethod> pre = new ArrayList<>();
|
||||
//获取该类本身的hook逻辑
|
||||
getHookMethodsList(post, pre, clazz);
|
||||
collectHookMethods(post, pre, clazz);
|
||||
//获取它所继承、实现的抽象类或接口, 以AgentInteractionModule、ActiveModel为终点
|
||||
List<Class<?>> classes = getExtendedClasses(clazz);
|
||||
Set<Class<?>> classes = collectSuperClasses(clazz);
|
||||
//获取这些类中的hook逻辑
|
||||
getHookMethodsList(post, pre, classes);
|
||||
collectHookMethods(post, pre, classes);
|
||||
return new MethodsListRecord(post, pre);
|
||||
}
|
||||
|
||||
private void getHookMethodsList(List<MetaMethod> post, List<MetaMethod> pre, List<Class<?>> classes) {
|
||||
|
||||
private void collectHookMethods(List<MetaMethod> post, List<MetaMethod> pre, Set<Class<?>> classes) {
|
||||
for (Class<?> type : classes) {
|
||||
collectPreHookMethods(pre, type);
|
||||
collectPostHookMethods(post, type);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Class<?>> getExtendedClasses(Class<?> clazz) {
|
||||
|
||||
return null;
|
||||
private void collectPostHookMethods(List<MetaMethod> post, Class<?> type) {
|
||||
Set<MetaMethod> collectedPostHookMethod = Arrays.stream(type.getMethods())
|
||||
.filter(method -> method.isAnnotationPresent(AfterExecute.class))
|
||||
.map(method -> {
|
||||
MetaMethod metaMethod = new MetaMethod();
|
||||
metaMethod.setMethod(method);
|
||||
metaMethod.setOrder(method.getAnnotation(AfterExecute.class).order());
|
||||
return metaMethod;
|
||||
})
|
||||
.collect(Collectors.toSet());
|
||||
post.addAll(collectedPostHookMethod);
|
||||
}
|
||||
|
||||
private void getHookMethodsList(List<MetaMethod> post, List<MetaMethod> pre, Class<?> clazz) {
|
||||
private void collectPreHookMethods(List<MetaMethod> pre, Class<?> type) {
|
||||
Set<MetaMethod> collectedPreHookMethods = Arrays.stream(type.getMethods())
|
||||
.filter(method -> method.isAnnotationPresent(BeforeExecute.class))
|
||||
.map(method -> {
|
||||
MetaMethod metaMethod = new MetaMethod();
|
||||
metaMethod.setMethod(method);
|
||||
metaMethod.setOrder(method.getAnnotation(BeforeExecute.class).order());
|
||||
return metaMethod;
|
||||
})
|
||||
.collect(Collectors.toSet());
|
||||
pre.addAll(collectedPreHookMethods);
|
||||
}
|
||||
|
||||
private Set<Class<?>> collectSuperClasses(Class<?> clazz) {
|
||||
Set<Class<?>> classes = new HashSet<>();
|
||||
collectSuperClasses(classes, clazz);
|
||||
return classes;
|
||||
}
|
||||
|
||||
private void collectSuperClasses(Set<Class<?>> classes, Class<?> clazz) {
|
||||
Class<?> superclass = clazz.getSuperclass();
|
||||
if (superclass == null || superclass == AgentInteractionModule.class) {
|
||||
return;
|
||||
}
|
||||
collectSuperClasses(classes, superclass);
|
||||
classes.add(superclass);
|
||||
collectInterfaces(clazz, classes);
|
||||
}
|
||||
|
||||
private void collectInterfaces(Class<?> clazz, Set<Class<?>> classes) {
|
||||
for (Class<?> type : clazz.getInterfaces()) {
|
||||
if (classes.add(type)) {
|
||||
collectInterfaces(type, classes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void collectHookMethods(List<MetaMethod> post, List<MetaMethod> pre, Class<?> clazz) {
|
||||
Method[] methods = clazz.getMethods();
|
||||
for (Method method : methods) {
|
||||
if (method.isAnnotationPresent(BeforeExecute.class)) {
|
||||
MetaMethod metaMethod = new MetaMethod();
|
||||
metaMethod.setOrder(method.getAnnotation(BeforeExecute.class).order());
|
||||
pre.add(metaMethod);
|
||||
metaMethod.setMethod(method);
|
||||
} else if (method.isAnnotationPresent(AfterExecute.class)) {
|
||||
MetaMethod metaMethod = new MetaMethod();
|
||||
metaMethod.setOrder(method.getAnnotation(AfterExecute.class).order());
|
||||
post.add(metaMethod);
|
||||
metaMethod.setMethod(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void generateInstances() {
|
||||
@@ -119,5 +191,9 @@ public class ModuleProxyFactory extends AgentBaseFactory {
|
||||
}
|
||||
|
||||
record MethodsListRecord(List<MetaMethod> post, List<MetaMethod> pre) {
|
||||
public MethodsListRecord {
|
||||
post.sort(Comparator.comparingInt(MetaMethod::getOrder));
|
||||
pre.sort(Comparator.comparingInt(MetaMethod::getOrder));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,7 @@ import org.reflections.Reflections;
|
||||
import work.slhaf.partner.api.factory.AgentBaseFactory;
|
||||
import work.slhaf.partner.api.factory.context.AgentRegisterContext;
|
||||
import work.slhaf.partner.api.factory.context.ModuleFactoryContext;
|
||||
import work.slhaf.partner.api.factory.module.annotation.AfterExecute;
|
||||
import work.slhaf.partner.api.factory.module.annotation.AgentModule;
|
||||
import work.slhaf.partner.api.factory.module.annotation.BeforeExecute;
|
||||
import work.slhaf.partner.api.factory.module.annotation.Init;
|
||||
import work.slhaf.partner.api.factory.module.pojo.MetaMethod;
|
||||
import work.slhaf.partner.api.factory.module.pojo.MetaModule;
|
||||
@@ -21,8 +19,6 @@ public class ModuleRegisterFactory extends AgentBaseFactory {
|
||||
|
||||
private Reflections reflections;
|
||||
private List<MetaModule> moduleList;
|
||||
private HashMap<Class<?>, Set<MetaMethod>> postHookMethods;
|
||||
private HashMap<Class<?>, Set<MetaMethod>> preHookMethods;
|
||||
private HashMap<Class<?>, Set<MetaMethod>> initHookMethods;
|
||||
|
||||
@Override
|
||||
@@ -30,23 +26,16 @@ public class ModuleRegisterFactory extends AgentBaseFactory {
|
||||
ModuleFactoryContext factoryContext = context.getModuleFactoryContext();
|
||||
reflections = context.getReflections();
|
||||
moduleList = factoryContext.getModuleList();
|
||||
postHookMethods = factoryContext.getPostHookMethods();
|
||||
preHookMethods = factoryContext.getPreHookMethods();
|
||||
initHookMethods = factoryContext.getInitHookMethods();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void run() {
|
||||
registerModuleList();
|
||||
registerHookSet();
|
||||
}
|
||||
|
||||
private void registerHookSet() {
|
||||
setPostHookMethods();
|
||||
setPreHookMethods();
|
||||
setModuleList();
|
||||
setInitMethods();
|
||||
}
|
||||
|
||||
|
||||
private void setInitMethods() {
|
||||
Set<Method> methods = reflections.getMethodsAnnotatedWith(Init.class);
|
||||
for (Method method : methods) {
|
||||
@@ -58,28 +47,6 @@ public class ModuleRegisterFactory extends AgentBaseFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private void setPreHookMethods() {
|
||||
Set<Method> methods = reflections.getMethodsAnnotatedWith(AfterExecute.class);
|
||||
for (Method method : methods) {
|
||||
MetaMethod metaMethod = new MetaMethod();
|
||||
metaMethod.setMethod(method);
|
||||
metaMethod.setOrder(method.getAnnotation(AfterExecute.class).order());
|
||||
|
||||
addMetaMethod(method, metaMethod, postHookMethods);
|
||||
}
|
||||
}
|
||||
|
||||
private void setPostHookMethods() {
|
||||
Set<Method> methods = reflections.getMethodsAnnotatedWith(BeforeExecute.class);
|
||||
for (Method method : methods) {
|
||||
MetaMethod metaMethod = new MetaMethod();
|
||||
metaMethod.setMethod(method);
|
||||
metaMethod.setOrder(method.getAnnotation(BeforeExecute.class).order());
|
||||
|
||||
addMetaMethod(method, metaMethod, preHookMethods);
|
||||
}
|
||||
}
|
||||
|
||||
private void addMetaMethod(Method method, MetaMethod metaMethod, HashMap<Class<?>, Set<MetaMethod>> preHookMethods) {
|
||||
Class<?> clazz = method.getDeclaringClass();
|
||||
if (preHookMethods.containsKey(clazz)) {
|
||||
@@ -91,7 +58,7 @@ public class ModuleRegisterFactory extends AgentBaseFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private void registerModuleList() {
|
||||
private void setModuleList() {
|
||||
//反射扫描获取@AgentModule所在类, 该部分为Agent流程执行模块
|
||||
Set<Class<?>> modules = reflections.getTypesAnnotatedWith(AgentModule.class);
|
||||
for (Class<?> module : modules) {
|
||||
|
||||
Reference in New Issue
Block a user