mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 16:53:04 +08:00
推进框架中的模块注册机制; 完善启动逻辑流程。
- 调整 InteractionFlowContext 为抽象类,实现者的模块上下文应当继承自该类。 - 完善 Agent 启动类具体逻辑 - 取消 Agent 类中 launchRunners 中关闭虚拟线程池的行为,交由JVM等待线程关闭,而非直接停止整个进程。 - 调整原hook注解分别为 BeforeExecute 、 AfterExecute,该注解用于模块抽象类的子类时可抽取重复逻辑 - 新增 Init 注解,用于执行初始化逻辑,可通过 order 属性指定顺序,默认为 0 - ModuleRegisterFactory 中新增‘加载 Init 注解标注的方法’的相关逻辑 - ModuleCheckFactory 添加对于 Init 注解的校验 - 完善了 ModuleProxyFactory 中设置代理实例的内容,可同时添加pre、post hook逻辑
This commit is contained in:
1
.idea/.gitignore
generated
vendored
1
.idea/.gitignore
generated
vendored
@@ -6,3 +6,4 @@
|
|||||||
# Datasource local storage ignored files
|
# Datasource local storage ignored files
|
||||||
/dataSources/
|
/dataSources/
|
||||||
/dataSources.local.xml
|
/dataSources.local.xml
|
||||||
|
/inspectionProfiles/Project_Default.xml
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
autoDetectedPackages:
|
autoDetectedPackages:
|
||||||
|
- module
|
||||||
- work.slhaf
|
- work.slhaf
|
||||||
enableAutoDetect: true
|
enableAutoDetect: true
|
||||||
entryDisplayConfig:
|
entryDisplayConfig:
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>1.18.36</version>
|
<version>1.18.36</version>
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package work.slhaf.partner.api;
|
package work.slhaf.partner.api;
|
||||||
|
|
||||||
import work.slhaf.partner.api.entity.AgentContext;
|
import work.slhaf.partner.api.exception.AgentLaunchFailedException;
|
||||||
import work.slhaf.partner.api.factory.AgentRegisterFactory;
|
import work.slhaf.partner.api.factory.AgentRegisterFactory;
|
||||||
|
import work.slhaf.partner.api.factory.module.pojo.MetaModule;
|
||||||
import work.slhaf.partner.api.flow.AgentInteraction;
|
import work.slhaf.partner.api.flow.AgentInteraction;
|
||||||
|
import work.slhaf.partner.api.flow.entity.InteractionFlowContext;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -14,23 +16,38 @@ import java.util.concurrent.Executors;
|
|||||||
*/
|
*/
|
||||||
public class Agent {
|
public class Agent {
|
||||||
|
|
||||||
private static final List<Runnable> runners = new ArrayList<>();
|
private final List<Runnable> runners = new ArrayList<>();
|
||||||
|
private final Class<?> applicationClass;
|
||||||
|
private final InteractionFlowContext interactionContext;
|
||||||
|
|
||||||
public static void run(Class<?> clazz) {
|
private Agent(Class<?> clazz, InteractionFlowContext interactionContext) {
|
||||||
AgentContext context = AgentRegisterFactory.launch(clazz.getPackage().getName());
|
this.applicationClass = clazz;
|
||||||
AgentInteraction.launch(context);
|
this.interactionContext = interactionContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Agent newAgent(Class<?> clazz, InteractionFlowContext interactionContext) {
|
||||||
|
if (clazz == null || interactionContext == null) {
|
||||||
|
throw new AgentLaunchFailedException("Agent class 和 interaction flow context 不能为 null");
|
||||||
|
}
|
||||||
|
return new Agent(clazz, interactionContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
List<MetaModule> moduleList = AgentRegisterFactory.launch(applicationClass.getPackage().getName());
|
||||||
|
AgentInteraction.launch(moduleList, interactionContext);
|
||||||
launchRunners();
|
launchRunners();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void launchRunners() {
|
|
||||||
|
private void launchRunners() {
|
||||||
ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor();
|
ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor();
|
||||||
for (Runnable runner : runners) {
|
for (Runnable runner : runners) {
|
||||||
executorService.execute(runner);
|
executorService.execute(runner);
|
||||||
}
|
}
|
||||||
executorService.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addRunner(Runnable runnable) {
|
public Agent addRunners(Runnable... runnable) {
|
||||||
runners.add(runnable);
|
runners.addAll(List.of(runnable));
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package work.slhaf.partner.api.entity;
|
package work.slhaf.partner.api.entity;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import work.slhaf.partner.api.factory.module.pojo.MetaModule;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
@@ -14,4 +16,5 @@ public class AgentContext {
|
|||||||
private HashMap<Class<?>, Object> capabilityHolderInstances;
|
private HashMap<Class<?>, Object> capabilityHolderInstances;
|
||||||
private Set<Class<?>> cores;
|
private Set<Class<?>> cores;
|
||||||
private Set<Class<?>> capabilities;
|
private Set<Class<?>> capabilities;
|
||||||
|
private List<MetaModule> moduleList;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package work.slhaf.partner.api.exception;
|
||||||
|
|
||||||
|
public class AgentLaunchFailedException extends RuntimeException {
|
||||||
|
public AgentLaunchFailedException(String message, Throwable cause) {
|
||||||
|
super("Agent 启动失败: " + message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AgentLaunchFailedException(String message) {
|
||||||
|
super("Agent 启动失败: " + message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
package work.slhaf.partner.api.factory;
|
package work.slhaf.partner.api.factory;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
|
||||||
import org.reflections.util.ClasspathHelper;
|
import org.reflections.util.ClasspathHelper;
|
||||||
import work.slhaf.partner.api.entity.AgentContext;
|
|
||||||
import work.slhaf.partner.api.factory.capability.CapabilityCheckFactory;
|
import work.slhaf.partner.api.factory.capability.CapabilityCheckFactory;
|
||||||
import work.slhaf.partner.api.factory.capability.CapabilityInjectFactory;
|
import work.slhaf.partner.api.factory.capability.CapabilityInjectFactory;
|
||||||
import work.slhaf.partner.api.factory.capability.CapabilityRegisterFactory;
|
import work.slhaf.partner.api.factory.capability.CapabilityRegisterFactory;
|
||||||
@@ -14,6 +12,7 @@ import work.slhaf.partner.api.factory.module.ModuleCheckFactory;
|
|||||||
import work.slhaf.partner.api.factory.module.ModulePreHookExecuteFactory;
|
import work.slhaf.partner.api.factory.module.ModulePreHookExecuteFactory;
|
||||||
import work.slhaf.partner.api.factory.module.ModuleProxyFactory;
|
import work.slhaf.partner.api.factory.module.ModuleProxyFactory;
|
||||||
import work.slhaf.partner.api.factory.module.ModuleRegisterFactory;
|
import work.slhaf.partner.api.factory.module.ModuleRegisterFactory;
|
||||||
|
import work.slhaf.partner.api.factory.module.pojo.MetaModule;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@@ -27,7 +26,7 @@ public class AgentRegisterFactory {
|
|||||||
private AgentRegisterFactory() {
|
private AgentRegisterFactory() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AgentContext launch(String packageName) {
|
public static List<MetaModule> launch(String packageName) {
|
||||||
urls.addAll(packageNameToURL(packageName));
|
urls.addAll(packageNameToURL(packageName));
|
||||||
AgentRegisterContext registerContext = new AgentRegisterContext(urls);
|
AgentRegisterContext registerContext = new AgentRegisterContext(urls);
|
||||||
//流程
|
//流程
|
||||||
@@ -46,11 +45,10 @@ public class AgentRegisterFactory {
|
|||||||
//. 执行模块PreHook逻辑
|
//. 执行模块PreHook逻辑
|
||||||
new ModulePreHookExecuteFactory().execute(registerContext);
|
new ModulePreHookExecuteFactory().execute(registerContext);
|
||||||
|
|
||||||
AgentContext agentContext = new AgentContext();
|
return registerContext.getModuleFactoryContext().getModuleList();
|
||||||
BeanUtil.copyProperties(registerContext, agentContext);
|
|
||||||
return agentContext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加可扫描包
|
* 添加可扫描包
|
||||||
* @param packageName 指定的包名
|
* @param packageName 指定的包名
|
||||||
|
|||||||
@@ -14,4 +14,5 @@ public class ModuleFactoryContext {
|
|||||||
private List<MetaModule> moduleList = new ArrayList<>();
|
private List<MetaModule> moduleList = new ArrayList<>();
|
||||||
private HashMap<Class<?>,Set<MetaMethod>> preHookMethods = new HashMap<>();
|
private HashMap<Class<?>,Set<MetaMethod>> preHookMethods = new HashMap<>();
|
||||||
private HashMap<Class<?>,Set<MetaMethod>> postHookMethods = new HashMap<>();
|
private HashMap<Class<?>,Set<MetaMethod>> postHookMethods = new HashMap<>();
|
||||||
|
private HashMap<Class<?>,Set<MetaMethod>> initHookMethods = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
package work.slhaf.partner.api.factory.module;
|
package work.slhaf.partner.api.factory.module;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ClassUtil;
|
||||||
import org.reflections.Reflections;
|
import org.reflections.Reflections;
|
||||||
import work.slhaf.partner.api.factory.AgentBaseFactory;
|
import work.slhaf.partner.api.factory.AgentBaseFactory;
|
||||||
import work.slhaf.partner.api.factory.config.ModelConfigManager;
|
import work.slhaf.partner.api.factory.config.ModelConfigManager;
|
||||||
import work.slhaf.partner.api.factory.context.AgentRegisterContext;
|
import work.slhaf.partner.api.factory.context.AgentRegisterContext;
|
||||||
import work.slhaf.partner.api.factory.module.annotation.After;
|
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.AgentModule;
|
||||||
import work.slhaf.partner.api.factory.module.annotation.Before;
|
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.exception.ModuleCheckException;
|
import work.slhaf.partner.api.factory.module.exception.ModuleCheckException;
|
||||||
import work.slhaf.partner.api.flow.abstracts.ActivateModel;
|
import work.slhaf.partner.api.flow.abstracts.ActivateModel;
|
||||||
import work.slhaf.partner.api.flow.abstracts.AgentInteractionModule;
|
import work.slhaf.partner.api.flow.abstracts.AgentInteractionModule;
|
||||||
@@ -68,14 +70,35 @@ public class ModuleCheckFactory extends AgentBaseFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void hookLocationCheck() {
|
private void hookLocationCheck() {
|
||||||
//检查@After注解
|
//检查@AfterExecute注解
|
||||||
postHookLocationCheck();
|
postHookLocationCheck();
|
||||||
//检查@Before注解
|
//检查@BeforeExecute注解
|
||||||
preHookLocationCheck();
|
preHookLocationCheck();
|
||||||
|
//检查@Init注解
|
||||||
|
initHookLocationCheck();
|
||||||
|
//检查@AgentModule注解是否只位于普通类上
|
||||||
|
agentModuleLocationCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void agentModuleLocationCheck() {
|
||||||
|
Set<Class<?>> types = reflections.getTypesAnnotatedWith(AgentModule.class);
|
||||||
|
for (Class<?> type : types) {
|
||||||
|
if (!ClassUtil.isNormalClass(type)) {
|
||||||
|
throw new ModuleCheckException("AgentModule 注解仅能位于普通类上! 异常类信息: " + type.getSimpleName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initHookLocationCheck() {
|
||||||
|
Set<Method> methods = reflections.getMethodsAnnotatedWith(Init.class);
|
||||||
|
Set<Class<?>> types = methods.stream()
|
||||||
|
.map(Method::getDeclaringClass)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
checkLocation(types);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void preHookLocationCheck() {
|
private void preHookLocationCheck() {
|
||||||
Set<Method> methods = reflections.getMethodsAnnotatedWith(Before.class);
|
Set<Method> methods = reflections.getMethodsAnnotatedWith(BeforeExecute.class);
|
||||||
Set<Class<?>> types = methods.stream()
|
Set<Class<?>> types = methods.stream()
|
||||||
.map(Method::getDeclaringClass)
|
.map(Method::getDeclaringClass)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
@@ -84,7 +107,7 @@ public class ModuleCheckFactory extends AgentBaseFactory {
|
|||||||
|
|
||||||
|
|
||||||
private void postHookLocationCheck() {
|
private void postHookLocationCheck() {
|
||||||
Set<Method> methods = reflections.getMethodsAnnotatedWith(After.class);
|
Set<Method> methods = reflections.getMethodsAnnotatedWith(AfterExecute.class);
|
||||||
Set<Class<?>> types = methods.stream()
|
Set<Class<?>> types = methods.stream()
|
||||||
.map(Method::getDeclaringClass)
|
.map(Method::getDeclaringClass)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package work.slhaf.partner.api.factory.module;
|
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.implementation.bind.annotation.*;
|
||||||
import net.bytebuddy.matcher.ElementMatchers;
|
|
||||||
import work.slhaf.partner.api.factory.AgentBaseFactory;
|
import work.slhaf.partner.api.factory.AgentBaseFactory;
|
||||||
import work.slhaf.partner.api.factory.context.AgentRegisterContext;
|
import work.slhaf.partner.api.factory.context.AgentRegisterContext;
|
||||||
import work.slhaf.partner.api.factory.context.ModuleFactoryContext;
|
import work.slhaf.partner.api.factory.context.ModuleFactoryContext;
|
||||||
@@ -11,59 +8,81 @@ import work.slhaf.partner.api.factory.module.exception.ModuleInstanceGenerateFai
|
|||||||
import work.slhaf.partner.api.factory.module.exception.ModuleProxyGenerateFailedException;
|
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.MetaMethod;
|
||||||
import work.slhaf.partner.api.factory.module.pojo.MetaModule;
|
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.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Comparator;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过扫描注解<code>@Before</code>,获取到各个模块的后hook逻辑并通过动态代理添加到执行逻辑之后
|
* 通过扫描注解<code>@BeforeExecute</code>,获取到各个模块的后hook逻辑并通过动态代理添加到执行逻辑之后
|
||||||
*/
|
*/
|
||||||
public class ModuleProxyFactory extends AgentBaseFactory {
|
public class ModuleProxyFactory extends AgentBaseFactory {
|
||||||
|
|
||||||
private List<MetaModule> moduleList;
|
private List<MetaModule> moduleList;
|
||||||
private HashMap<Class<?>, Set<MetaMethod>> postHookMethods;
|
private HashMap<Class<?>, Set<MetaMethod>> postHookMethods;
|
||||||
|
private HashMap<Class<?>, Set<MetaMethod>> preHookMethods;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setVariables(AgentRegisterContext context) {
|
protected void setVariables(AgentRegisterContext context) {
|
||||||
ModuleFactoryContext factoryContext = context.getModuleFactoryContext();
|
ModuleFactoryContext factoryContext = context.getModuleFactoryContext();
|
||||||
moduleList = factoryContext.getModuleList();
|
moduleList = factoryContext.getModuleList();
|
||||||
postHookMethods = factoryContext.getPostHookMethods();
|
postHookMethods = factoryContext.getPostHookMethods();
|
||||||
|
preHookMethods = factoryContext.getPreHookMethods();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void run() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
protected void run() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
||||||
//TODO 生成实例、并通过动态代理添加PostHook逻辑
|
//TODO 填充具体逻辑
|
||||||
generateInstances();
|
generateInstances();
|
||||||
setPostHookProxy();
|
setHookProxy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPostHookProxy() {
|
private void setHookProxy() {
|
||||||
for (MetaModule module : moduleList) {
|
for (MetaModule module : moduleList) {
|
||||||
Class<?> clazz = module.getClazz();
|
Class<?> clazz = module.getClazz();
|
||||||
try {
|
try {
|
||||||
Class<?> proxyClass = new ByteBuddy()
|
MethodsListRecord record = getHookMethodsList(clazz);
|
||||||
.subclass(clazz)
|
//生成实例,
|
||||||
.method(ElementMatchers.isOverriddenFrom(AgentInteractionModule.class))
|
generateProxiedInstances(record);
|
||||||
.intercept(MethodDelegation.to(new ModuleProxyInterceptor(postHookMethods.get(clazz).stream().sorted(Comparator.comparing(MetaMethod::getOrder)).toList())))
|
|
||||||
.make()
|
|
||||||
.load(ModuleProxyFactory.class.getClassLoader())
|
|
||||||
.getLoaded();
|
|
||||||
|
|
||||||
AgentInteractionModule interactionModule = (AgentInteractionModule) proxyClass.getConstructor().newInstance();
|
|
||||||
//TODO 检测代理写法是否正确
|
|
||||||
//TODO 添加ModuleManager,负责统一管理Module的加载、卸载
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new ModuleProxyGenerateFailedException("创建代理对象失败: " + clazz.getSimpleName(), e);
|
throw new ModuleProxyGenerateFailedException("创建代理对象失败: " + clazz.getSimpleName(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void generateProxiedInstances(MethodsListRecord record) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private MethodsListRecord getHookMethodsList(Class<?> clazz) {
|
||||||
|
List<MetaMethod> post = new ArrayList<>();
|
||||||
|
List<MetaMethod> pre = new ArrayList<>();
|
||||||
|
//获取该类本身的hook逻辑
|
||||||
|
getHookMethodsList(post, pre, clazz);
|
||||||
|
//获取它所继承、实现的抽象类或接口, 以AgentInteractionModule、ActiveModel为终点
|
||||||
|
List<Class<?>> classes = getExtendedClasses(clazz);
|
||||||
|
//获取这些类中的hook逻辑
|
||||||
|
getHookMethodsList(post, pre, classes);
|
||||||
|
return new MethodsListRecord(post, pre);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getHookMethodsList(List<MetaMethod> post, List<MetaMethod> pre, List<Class<?>> classes) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Class<?>> getExtendedClasses(Class<?> clazz) {
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getHookMethodsList(List<MetaMethod> post, List<MetaMethod> pre, Class<?> clazz) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void generateInstances() {
|
private void generateInstances() {
|
||||||
for (MetaModule metaModule : moduleList) {
|
for (MetaModule metaModule : moduleList) {
|
||||||
try {
|
try {
|
||||||
@@ -78,19 +97,27 @@ public class ModuleProxyFactory extends AgentBaseFactory {
|
|||||||
|
|
||||||
private static class ModuleProxyInterceptor {
|
private static class ModuleProxyInterceptor {
|
||||||
|
|
||||||
private List<MetaMethod> postHookMethods;
|
private final List<MetaMethod> postHookMethods;
|
||||||
|
private final List<MetaMethod> preHookMethods;
|
||||||
|
|
||||||
private ModuleProxyInterceptor(List<MetaMethod> postHookMethods) {
|
private ModuleProxyInterceptor(List<MetaMethod> postHookMethods, List<MetaMethod> preHookMethods) {
|
||||||
this.postHookMethods = postHookMethods;
|
this.postHookMethods = postHookMethods;
|
||||||
|
this.preHookMethods = preHookMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
@RuntimeType
|
@RuntimeType
|
||||||
public Object intercept(@Origin Method method, @AllArguments Object[] allArguments, @SuperCall Callable<?> zuper, @This Object proxy) throws Exception {
|
public Object intercept(@Origin Method method, @AllArguments Object[] allArguments, @SuperCall Callable<?> zuper, @This Object proxy) throws Exception {
|
||||||
|
for (MetaMethod metaMethod : preHookMethods) {
|
||||||
|
metaMethod.getMethod().invoke(proxy);
|
||||||
|
}
|
||||||
Object res = zuper.call();
|
Object res = zuper.call();
|
||||||
for (MetaMethod metaMethod : postHookMethods) {
|
for (MetaMethod metaMethod : postHookMethods) {
|
||||||
metaMethod.getMethod().invoke(proxy, allArguments);
|
metaMethod.getMethod().invoke(proxy);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
record MethodsListRecord(List<MetaMethod> post, List<MetaMethod> pre) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import org.reflections.Reflections;
|
|||||||
import work.slhaf.partner.api.factory.AgentBaseFactory;
|
import work.slhaf.partner.api.factory.AgentBaseFactory;
|
||||||
import work.slhaf.partner.api.factory.context.AgentRegisterContext;
|
import work.slhaf.partner.api.factory.context.AgentRegisterContext;
|
||||||
import work.slhaf.partner.api.factory.context.ModuleFactoryContext;
|
import work.slhaf.partner.api.factory.context.ModuleFactoryContext;
|
||||||
import work.slhaf.partner.api.factory.module.annotation.After;
|
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.AgentModule;
|
||||||
import work.slhaf.partner.api.factory.module.annotation.Before;
|
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.MetaMethod;
|
||||||
import work.slhaf.partner.api.factory.module.pojo.MetaModule;
|
import work.slhaf.partner.api.factory.module.pojo.MetaModule;
|
||||||
|
|
||||||
@@ -22,6 +23,7 @@ public class ModuleRegisterFactory extends AgentBaseFactory {
|
|||||||
private List<MetaModule> moduleList;
|
private List<MetaModule> moduleList;
|
||||||
private HashMap<Class<?>, Set<MetaMethod>> postHookMethods;
|
private HashMap<Class<?>, Set<MetaMethod>> postHookMethods;
|
||||||
private HashMap<Class<?>, Set<MetaMethod>> preHookMethods;
|
private HashMap<Class<?>, Set<MetaMethod>> preHookMethods;
|
||||||
|
private HashMap<Class<?>, Set<MetaMethod>> initHookMethods;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setVariables(AgentRegisterContext context) {
|
protected void setVariables(AgentRegisterContext context) {
|
||||||
@@ -30,6 +32,7 @@ public class ModuleRegisterFactory extends AgentBaseFactory {
|
|||||||
moduleList = factoryContext.getModuleList();
|
moduleList = factoryContext.getModuleList();
|
||||||
postHookMethods = factoryContext.getPostHookMethods();
|
postHookMethods = factoryContext.getPostHookMethods();
|
||||||
preHookMethods = factoryContext.getPreHookMethods();
|
preHookMethods = factoryContext.getPreHookMethods();
|
||||||
|
initHookMethods = factoryContext.getInitHookMethods();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -41,25 +44,37 @@ public class ModuleRegisterFactory extends AgentBaseFactory {
|
|||||||
private void registerHookSet() {
|
private void registerHookSet() {
|
||||||
setPostHookMethods();
|
setPostHookMethods();
|
||||||
setPreHookMethods();
|
setPreHookMethods();
|
||||||
|
setInitMethods();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPreHookMethods() {
|
private void setInitMethods() {
|
||||||
Set<Method> methods = reflections.getMethodsAnnotatedWith(After.class);
|
Set<Method> methods = reflections.getMethodsAnnotatedWith(Init.class);
|
||||||
for (Method method : methods) {
|
for (Method method : methods) {
|
||||||
MetaMethod metaMethod = new MetaMethod();
|
MetaMethod metaMethod = new MetaMethod();
|
||||||
metaMethod.setMethod(method);
|
metaMethod.setMethod(method);
|
||||||
metaMethod.setOrder(method.getAnnotation(After.class).order());
|
metaMethod.setOrder(method.getAnnotation(Init.class).order());
|
||||||
|
|
||||||
|
addMetaMethod(method, metaMethod, initHookMethods);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
addMetaMethod(method, metaMethod, postHookMethods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPostHookMethods() {
|
private void setPostHookMethods() {
|
||||||
Set<Method> methods = reflections.getMethodsAnnotatedWith(Before.class);
|
Set<Method> methods = reflections.getMethodsAnnotatedWith(BeforeExecute.class);
|
||||||
for (Method method : methods) {
|
for (Method method : methods) {
|
||||||
MetaMethod metaMethod = new MetaMethod();
|
MetaMethod metaMethod = new MetaMethod();
|
||||||
metaMethod.setMethod(method);
|
metaMethod.setMethod(method);
|
||||||
metaMethod.setOrder(method.getAnnotation(Before.class).order());
|
metaMethod.setOrder(method.getAnnotation(BeforeExecute.class).order());
|
||||||
|
|
||||||
addMetaMethod(method, metaMethod, preHookMethods);
|
addMetaMethod(method, metaMethod, preHookMethods);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,6 @@ import java.lang.annotation.Target;
|
|||||||
|
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface After {
|
public @interface AfterExecute {
|
||||||
int order() default 0;
|
int order() default 0;
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,6 @@ import java.lang.annotation.Target;
|
|||||||
*/
|
*/
|
||||||
@Target(ElementType.METHOD)
|
@Target(ElementType.METHOD)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Before {
|
public @interface BeforeExecute {
|
||||||
int order() default 0;
|
int order() default 0;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package work.slhaf.partner.api.factory.module.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
public @interface Init {
|
||||||
|
int order() default 0;
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
package work.slhaf.partner.api.flow;
|
package work.slhaf.partner.api.flow;
|
||||||
|
|
||||||
import work.slhaf.partner.api.entity.AgentContext;
|
import work.slhaf.partner.api.factory.module.pojo.MetaModule;
|
||||||
|
import work.slhaf.partner.api.flow.entity.InteractionFlowContext;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Agent执行流程
|
* Agent执行流程
|
||||||
@@ -9,7 +12,7 @@ public class AgentInteraction {
|
|||||||
|
|
||||||
private AgentInteraction(){}
|
private AgentInteraction(){}
|
||||||
|
|
||||||
public static void launch(AgentContext context){
|
public static void launch(List<MetaModule> moduleList, InteractionFlowContext interactionContext){
|
||||||
//流程执行启动,需考虑模块热插拔,可结合http调整模块启用情况,并序列化至本地或数据库中
|
//流程执行启动,需考虑模块热插拔,可结合http调整模块启用情况,并序列化至本地或数据库中
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ import work.slhaf.partner.api.common.chat.pojo.ChatResponse;
|
|||||||
import work.slhaf.partner.api.common.chat.pojo.Message;
|
import work.slhaf.partner.api.common.chat.pojo.Message;
|
||||||
import work.slhaf.partner.api.factory.config.ModelConfigManager;
|
import work.slhaf.partner.api.factory.config.ModelConfigManager;
|
||||||
import work.slhaf.partner.api.factory.config.pojo.ModelConfig;
|
import work.slhaf.partner.api.factory.config.pojo.ModelConfig;
|
||||||
import work.slhaf.partner.api.factory.module.annotation.Before;
|
import work.slhaf.partner.api.factory.module.annotation.BeforeExecute;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface ActivateModel {
|
public interface ActivateModel {
|
||||||
|
|
||||||
@Before
|
@BeforeExecute
|
||||||
default void modelSettings() {
|
default void modelSettings() {
|
||||||
Model model = new Model();
|
Model model = new Model();
|
||||||
ModelConfig modelConfig = ModelConfigManager.INSTANCE.loadModelConfig(modelKey());
|
ModelConfig modelConfig = ModelConfigManager.INSTANCE.loadModelConfig(modelKey());
|
||||||
|
|||||||
@@ -6,5 +6,6 @@ import lombok.Data;
|
|||||||
* 流程上下文
|
* 流程上下文
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class InteractionFlowContext {
|
public abstract class InteractionFlowContext {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
7
Partner-Api/src/test/java/TestApplication.java
Normal file
7
Partner-Api/src/test/java/TestApplication.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import work.slhaf.partner.api.Agent;
|
||||||
|
|
||||||
|
public class TestApplication {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Agent.newAgent(TestApplication.class,null).run();
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Partner-Api/src/test/java/module/ModuleProxyTest.java
Normal file
24
Partner-Api/src/test/java/module/ModuleProxyTest.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package module;
|
||||||
|
|
||||||
|
import net.bytebuddy.ByteBuddy;
|
||||||
|
import net.bytebuddy.implementation.MethodDelegation;
|
||||||
|
import net.bytebuddy.matcher.ElementMatchers;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import work.slhaf.partner.api.flow.abstracts.AgentInteractionModule;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
public class ModuleProxyTest {
|
||||||
|
@Test
|
||||||
|
public void test() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
||||||
|
Class<? extends AgentInteractionModule> clazz = new ByteBuddy().subclass(MyAgentInteractionModule.class)
|
||||||
|
.method(ElementMatchers.isOverriddenFrom(AgentInteractionModule.class))
|
||||||
|
.intercept(MethodDelegation.to(
|
||||||
|
new MyModuleProxyInterceptor()
|
||||||
|
))
|
||||||
|
.make()
|
||||||
|
.load(ModuleProxyTest.class.getClassLoader())
|
||||||
|
.getLoaded();
|
||||||
|
clazz.getConstructor().newInstance().execute(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package module;
|
||||||
|
|
||||||
|
import work.slhaf.partner.api.flow.abstracts.AgentInteractionModule;
|
||||||
|
import work.slhaf.partner.api.flow.entity.InteractionFlowContext;
|
||||||
|
|
||||||
|
public class MyAgentInteractionModule extends AgentInteractionModule {
|
||||||
|
@Override
|
||||||
|
public void execute(InteractionFlowContext context) {
|
||||||
|
System.out.println("MyAgentInteractionModule");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package module;
|
||||||
|
|
||||||
|
import net.bytebuddy.implementation.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
public class MyModuleProxyInterceptor {
|
||||||
|
public MyModuleProxyInterceptor() {}
|
||||||
|
|
||||||
|
@RuntimeType
|
||||||
|
public Object intercept(@Origin Method method, @AllArguments Object[] allArguments, @SuperCall Callable<?> zuper, @This Object proxy) throws Exception {
|
||||||
|
System.out.println("22222");
|
||||||
|
Object res = zuper.call();
|
||||||
|
System.out.println("11111");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user