entry : javaMemClassMap.entrySet()) {
- classLoader.addClassMap(entry.getKey(), entry.getValue().getBytes());
- }
- }
-
- /**
- * 动态编译并加载Java源代码。
- *
- * 该方法接收Java源代码和完整的类名作为参数,通过动态编译源代码并使用自定义类加载器加载生成的类,实现动态代码的执行。
- * 这种方式常用于运行时生成和执行代码,例如在某些框架中用于动态生成代理类。
- *
- * @param javaSourceCode Java源代码字符串。
- * @param fullClassName 完整的类名,包括包名。
- * @return 编译并加载后的类的Class对象。
- * @throws LoaderRuntimeException 如果编译或加载过程中发生错误,将抛出此运行时异常。
- */
- public static Class> compilerOnce(String javaSourceCode, String fullClassName) {
- // 使用JavaBuilder编译Java源代码,生成内存中的类对象。
- Map javaMemClassMap = JavaBuilder.builder().compiler(javaSourceCode, fullClassName).getJavaMemClassMap();
-
- try (DynamicClassLoader dynamicClassLoader = new DynamicClassLoader(Thread.currentThread().getContextClassLoader())) {
- // 将内存中的类信息添加到自定义类加载器的类映射中。
- for (Map.Entry entry : javaMemClassMap.entrySet()) {
- dynamicClassLoader.addClassMap(entry.getKey(), entry.getValue().getBytes());
- }
- // 使用自定义类加载器加载指定的类。
- return dynamicClassLoader.loadClass(fullClassName);
- } catch (IOException | ClassNotFoundException e) {
- // 抛出自定义异常,以更清晰地指示编译或加载过程中的错误。
- throw new LoaderRuntimeException(e.getMessage(), e);
- }
- }
-
- /**
- * 通过类名加载类。
- *
- * @param fullClassName 完全限定类名。
- * @return 加载的类。
- */
- public static Class> load(String fullClassName) {
- try {
- // 获取动态类加载器实例并加载类
- DynamicClassLoader classLoader = DynamicClassLoader.getInstance();
- return classLoader.loadClass(fullClassName);
- } catch (ClassNotFoundException e) {
- // 抛出运行时异常,携带错误信息
- throw new LoaderRuntimeException(e.getMessage(), e);
- }
- }
-
- /**
- * 将JAR路径添加到类路径中。
- *
- * @param jarPath JAR文件路径。
- */
- public static void addJarPath(String jarPath) {
- try {
- // 获取动态类加载器实例并添加JAR路径
- DynamicClassLoader.getInstance().addURL(new URL("jar:file:" + new File(jarPath).getAbsolutePath() + "!/"));
- } catch (MalformedURLException e) {
- // 抛出运行时异常,携带错误信息
- throw new LoaderRuntimeException(e.getMessage(), e);
- }
- }
-
- /**
- * 注册单例 bean 到 Spring 应用上下文中。
- *
- * 此方法用于将指定的类作为单例 bean 注册到 Spring 应用上下文中。如果该类已经注册为 bean,则先销毁已存在的 bean 实例,然后重新注册。
- * 这确保了应用上下文中只有一个该类的实例存在。
- *
- * @param clazz 要注册为单例 bean 的类。
- * @return 注册后的 bean 名称。
- */
- public static String registerSingleton(Class> clazz) {
- // 通过类名生成 bean 名称。
- String beanName = SpringContextUtils.beanName(clazz.getName());
- // 检查是否已存在同名的 bean。如果存在,则先销毁该 bean。
- if (Boolean.TRUE.equals(SpringContextUtils.containsBean(beanName))) {
- SpringContextUtils.destroy(beanName);
- }
- // 注册指定类为单例 bean。
- SpringContextUtils.registerSingleton(beanName, clazz);
- // 返回注册后的 bean 名称。
- return beanName;
- }
-
- /**
- * 注册控制器类到Spring上下文中。
- *
- * 本方法用于将给定的控制器类注册到Spring应用程序上下文中。如果该类已经注册,则先注销原有的实例,再重新注册。
- * 这确保了Spring上下文中总是存在最新版本的控制器类实例。
- *
- * @param clazz 待注册的控制器类。此参数不应为null。
- * @return 注册后的bean名称。如果给定的类已经被注册,则返回更新后的bean名称。
- */
- public static String registerController(Class> clazz) {
- // 通过类名生成bean名称
- String beanName = SpringContextUtils.beanName(clazz.getName());
- // 检查是否已经存在同名的bean
- if (Boolean.TRUE.equals(SpringContextUtils.containsBean(beanName)))
- // 如果存在,则先注销原有的bean
- SpringContextUtils.unregisterController(beanName);
- // 注册新的控制器类
- SpringContextUtils.registerController(beanName, clazz);
- // 返回注册后的bean名称
- return beanName;
- }
-
- /**
- * 清理动态类加载器的缓存。
- *
- * 该方法调用了DynamicClassLoader的clear方法,旨在清理动态加载的类,以释放内存资源。
- * 当系统不再需要这些动态加载的类,或者需要重新加载类时,可以调用此方法。
- */
- public static void clear() {
- DynamicClassLoader.clear();
- }
-}
-
diff --git a/src/main/java/cn/wubo/loader/util/MethodUtils.java b/src/main/java/cn/wubo/loader/util/MethodUtils.java
deleted file mode 100644
index e3a4f45314fcdb2a8edcf2fb57f4ed3c4522f10c..0000000000000000000000000000000000000000
--- a/src/main/java/cn/wubo/loader/util/MethodUtils.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package cn.wubo.loader.util;
-
-import cn.wubo.loader.util.aspect.AspectHandler;
-import cn.wubo.loader.util.aspect.IAspect;
-import cn.wubo.loader.util.aspect.SimpleAspect;
-import cn.wubo.loader.util.exception.LoaderRuntimeException;
-import org.springframework.cglib.proxy.Enhancer;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-
-/**
- * 执行方法和代理切面工具类
- */
-public class MethodUtils {
-
- private MethodUtils() {
- }
-
- /**
- * 执行类中的方法
- *
- * @param clazz 目标类
- * @param methodName 目标方法名
- * @param args 参数
- * @return 返回值,Object类型
- */
- public static Object invokeClass(Class> clazz, String methodName, Object... args) {
- try {
- Object o = clazz.getConstructor().newInstance(); // 创建目标类的实例对象
- Class>[] parameterTypes = Arrays.stream(args).map(Object::getClass).toList().toArray(new Class>[]{}); // 获取参数的类型
- Method method = clazz.getDeclaredMethod(methodName, parameterTypes); // 获取目标方法
- method.setAccessible(true); // 设置方法可访问
- return method.invoke(o, args); // 调用目标方法并返回结果
- } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
- NoSuchMethodException e) {
- throw new LoaderRuntimeException(e.getMessage(), e); // 抛出运行时异常
- }
- }
-
-
- /**
- * 执行对象中的方法
- *
- * @param target 目标对象
- * @param methodName 目标方法名
- * @param args 参数
- * @return 返回值,泛型
- */
- public static R invokeClass(T target, String methodName, Object... args) {
- try {
- // 获取参数类型数组
- Class>[] parameterTypes = Arrays.stream(args).map(Object::getClass).toList().toArray(new Class>[]{});
- // 获取目标对象对应方法的实例
- Method method = target.getClass().getDeclaredMethod(methodName, parameterTypes);
- // 设置方法可访问性
- method.setAccessible(true);
- // 调用目标方法并返回结果
- return (R) method.invoke(target, args);
- } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
- throw new LoaderRuntimeException(e.getMessage(), e);
- }
- }
-
-
- /**
- * 执行Bean中的方法
- *
- * @param beanName 目标bean名称
- * @param methodName 目标方法名
- * @param args 参数
- * @return 返回值,泛型
- */
- public static R invokeBean(String beanName, String methodName, Object... args) {
- return (R) invokeBeanReturnObject(beanName, methodName, args);
- }
-
-
- /**
- * 执行Bean中的方法
- *
- * @param beanName 目标bean名称
- * @param methodName 目标方法名
- * @param args 参数
- * @return 返回值, Object类型
- */
- public static Object invokeBeanReturnObject(String beanName, String methodName, Object... args) {
- try {
- Object obj = SpringContextUtils.getBean(beanName);
- Class>[] parameterTypes = Arrays.stream(args).map(Object::getClass).toList().toArray(new Class>[]{});
- Method method = obj.getClass().getMethod(methodName, parameterTypes);
- method.setAccessible(true);
- return method.invoke(obj, args);
- } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
- throw new LoaderRuntimeException(e.getMessage(), e);
- }
- }
-
- /**
- * 使用切面代理对象,默认使用SimpleAspect切面
- *
- * @param target 目标对象
- * @return 被代理的切面,Object类型
- */
- public static T proxy(T target) {
- return proxy(target, new SimpleAspect());
- }
-
-
- /**
- * 使用切面代理对象
- *
- * @param target 目标对象
- * @param aspectClass 切面类
- * @return 被代理的切面,Object类型
- */
- public static T proxy(T target, Class aspectClass) {
- try {
- return proxy(target, aspectClass.getConstructor().newInstance());
- } catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
- InvocationTargetException e) {
- throw new LoaderRuntimeException(e.getMessage(), e);
- }
- }
-
-
- /**
- * 使用切面代理对象
- *
- * @param target 目标对象
- * @param aspectTarget 切面对象
- * @return 被代理的切面
- */
- public static T proxy(T target, E aspectTarget) {
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(target.getClass());
- enhancer.setCallback(new AspectHandler(target, aspectTarget));
- return (T) enhancer.create();
- }
-
-}
diff --git a/src/main/java/cn/wubo/loader/util/SpringContextUtils.java b/src/main/java/cn/wubo/loader/util/SpringContextUtils.java
deleted file mode 100644
index 50ddf180a26a15f9eaf3b6dac69b133af5ce2930..0000000000000000000000000000000000000000
--- a/src/main/java/cn/wubo/loader/util/SpringContextUtils.java
+++ /dev/null
@@ -1,194 +0,0 @@
-package cn.wubo.loader.util;
-
-import cn.wubo.loader.util.exception.LoaderRuntimeException;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.BeanFactoryAware;
-import org.springframework.beans.factory.support.DefaultListableBeanFactory;
-import org.springframework.stereotype.Component;
-import org.springframework.util.ClassUtils;
-import org.springframework.util.ReflectionUtils;
-import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
-import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Map;
-
-@Component(value = "loaderUtilSpringContextUtils")
-public class SpringContextUtils implements BeanFactoryAware {
-
- private static DefaultListableBeanFactory listableBeanFactory;
-
- @Override
- public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
- listableBeanFactory = (DefaultListableBeanFactory) beanFactory;
- }
-
- /**
- * 注册一个单例bean。此方法为泛型方法,允许注册任何类型的单例对象。
- * 通过传入类类型,系统可以在运行时创建该类型的单例实例。
- *
- * @param type 类类型,表示要注册为单例的类。
- * @param 类型参数,表示泛型类型。
- */
- public static void registerSingleton(Class type) {
- // 使用类的名称作为bean的名称来注册单例
- registerSingleton(beanName(type.getName()), type);
- }
-
- /**
- * 注册一个单例对象到Spring Bean工厂。
- *
- * 该方法通过以下步骤实现单例注册:
- * 1. 使用提供的类型创建一个对象实例。
- * 2. 对该对象进行自动装配,使其能够与其他Spring管理的bean进行依赖注入。
- * 3. 将该对象注册为一个单例bean,使用提供的bean名称进行标识。
- *
- * @param beanName 将要注册的bean的名称。
- * @param type bean的类型,用于创建对象实例。
- * @param 泛型参数,指定bean的类型。
- */
- public static void registerSingleton(String beanName, Class type) {
- // 根据提供的类型创建bean实例。
- T obj = listableBeanFactory.createBean(type);
- // 对创建的bean实例进行自动装配。
- listableBeanFactory.autowireBean(obj);
- // 将装配好的bean实例注册为单例。
- listableBeanFactory.registerSingleton(beanName, obj);
- }
-
- /**
- * 注册控制器类并触发Spring MVC的映射处理方法。
- *
- * 本方法主要用于在运行时动态注册控制器类,使得这些类能够被Spring MVC框架识别并处理相应的HTTP请求。
- * 通过调用registerSingleton方法将控制器类注册为Spring Bean,确保Spring容器能够管理这个类的实例。
- * 随后,通过获取RequestMappingHandlerMapping实例并调用其detectHandlerMethods方法,来触发Spring MVC对新注册控制器的映射处理。
- * 这一过程对于动态加载控制器类,例如在插件开发或者热部署场景中,是非常关键的。
- *
- * @param beanName 控制器类在Spring容器中的Bean名称。
- * @param type 控制器类的类型。
- * @throws LoaderRuntimeException 如果在尝试检测处理器方法过程中发生异常,则抛出此运行时异常。
- * @param 控制器类的类型参数。
- */
- public static void registerController(String beanName, Class type) {
- // 注册控制器类为Spring Bean。
- registerSingleton(beanName, type);
-
- // 获取RequestMappingHandlerMapping实例,用于处理请求映射。
- RequestMappingHandlerMapping requestMappingHandlerMapping = getBean("requestMappingHandlerMapping");
-
- try {
- // 通过反射获取父类的父类(即AbstractHandlerMethodMapping)中的detectHandlerMethods方法。
- // 这是因为RequestMappingHandlerMapping自身并没有提供公开的detectHandlerMethods方法。
- Method method = requestMappingHandlerMapping.getClass().getSuperclass().getSuperclass().getDeclaredMethod("detectHandlerMethods", Object.class);
- // 设置方法可访问,以绕过Java的访问控制。
- method.setAccessible(true);
- // 调用detectHandlerMethods方法,传入控制器Bean的名称,以触发映射处理。
- method.invoke(requestMappingHandlerMapping, beanName);
- } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
- // 如果在处理过程中发生异常,则抛出自定义的运行时异常。
- throw new LoaderRuntimeException(e.getMessage(), e);
- }
- }
-
- /**
- * 取消注册一个控制器(bean)。
- * 该方法通过获取特定bean实例,分析并移除其上的@RequestMapping映射,从而实现控制器的注销功能。
- * 主要用于在运行时动态调整应用程序的路由配置。
- *
- * @param beanName 需要注销的控制器bean的名称。
- */
- public static void unregisterController(String beanName) {
- // 根据bean名称获取bean实例。
- Object obj = getBean(beanName);
- // 获取bean实例的类类型。
- Class> type = obj.getClass();
-
- // 获取RequestMappingHandlerMapping的实例,用于处理@RequestMapping的映射注销。
- RequestMappingHandlerMapping requestMappingHandlerMapping = getBean("requestMappingHandlerMapping");
-
- // 遍历类型上的所有方法,寻找并处理@RequestMapping注解的方法。
- ReflectionUtils.doWithMethods(type, method -> {
- // 获取最具体的方法,用于处理重载方法的情况。
- Method mostSpecificMethod = ClassUtils.getMostSpecificMethod(method, type);
- try {
- // 获取RequestMappingHandlerMapping中用于获取方法映射的方法。
- Method declaredMethod = requestMappingHandlerMapping.getClass().getDeclaredMethod("getMappingForMethod", Method.class, Class.class);
- // 设置该方法可访问,因为它是protected的。
- declaredMethod.setAccessible(true);
- // 调用getMappingForMethod方法,获取对应方法的RequestMappingInfo对象。
- RequestMappingInfo requestMappingInfo = (RequestMappingInfo) declaredMethod.invoke(requestMappingHandlerMapping, mostSpecificMethod, type);
- // 如果RequestMappingInfo不为空,则从映射中注销该方法。
- if (requestMappingInfo != null) requestMappingHandlerMapping.unregisterMapping(requestMappingInfo);
- } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
- // 抛出运行时异常,封装原始异常信息。
- throw new LoaderRuntimeException(e.getMessage(), e);
- }
- });
- // 销毁单例bean,确保它在容器中被重新创建而不是重新使用。
- listableBeanFactory.destroySingleton(beanName);
- }
-
- /**
- * 判断是否包含指定类型的bean
- *
- * @param type 要判断的bean类型
- * @return 如果包含指定类型的bean则返回true,否则返回false
- */
- public static Boolean containsBean(Class type) {
- return listableBeanFactory.containsBean(beanName(type.getName()));
- }
-
- /**
- * 判断给定的bean名称是否存在于listableBeanFactory中
- *
- * @param beanName 要判断的bean名称
- * @return 如果bean名称存在于listableBeanFactory中,则返回true;否则返回false
- */
- public static Boolean containsBean(String beanName) {
- return listableBeanFactory.containsBean(beanName);
- }
-
- /**
- * 销毁指定名称的单例对象。
- *
- * @param beanName 要销毁的单例对象的名称
- */
- public static void destroy(String beanName) {
- listableBeanFactory.destroySingleton(beanName);
- }
-
- /**
- * 销毁指定类型的单例对象。
- *
- * @param type 指定的类型
- */
- public static void destroy(Class type) {
- listableBeanFactory.destroySingleton(beanName(type.getName()));
- }
-
- /**
- * 生成bean的名称
- *
- * @param className 类名
- * @return bean的名称
- */
- public static String beanName(String className) {
- String[] path = className.split("\\.");
- String beanName = path[path.length - 1];
- return Character.toLowerCase(beanName.charAt(0)) + beanName.substring(1);
- }
-
- public static T getBean(String name) {
- return (T) listableBeanFactory.getBean(name);
- }
-
- public static T getBean(Class type) {
- return listableBeanFactory.getBean(type);
- }
-
- public static Map getBeans(Class type) {
- return listableBeanFactory.getBeansOfType(type);
- }
-}
diff --git a/src/main/java/cn/wubo/loader/util/class_loader/DynamicClassLoader.java b/src/main/java/cn/wubo/loader/util/class_loader/DynamicClassLoader.java
deleted file mode 100644
index 56b20bd60180b6dc3c3220f634777d4901d80cca..0000000000000000000000000000000000000000
--- a/src/main/java/cn/wubo/loader/util/class_loader/DynamicClassLoader.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package cn.wubo.loader.util.class_loader;
-
-import cn.wubo.loader.util.exception.LoaderRuntimeException;
-import lombok.Getter;
-import lombok.extern.slf4j.Slf4j;
-
-import java.io.IOException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 动态类加载器,扩展自URLClassLoader,支持动态加载类。
- * 通过将类的字节码与类名映射,实现动态加载和查找类的功能。
- */
-@Slf4j
-public class DynamicClassLoader extends URLClassLoader {
-
- /**
- * 类映射,存储类的完全限定名和对应的Class对象。
- */
- private Map> classMap = new HashMap<>();
-
- /**
- * 构造函数,使用当前线程的上下文类加载器作为父类加载器。
- *
- * @param parent 父类加载器
- */
- public DynamicClassLoader(ClassLoader parent) {
- super(new URL[0], parent);
- }
-
- /**
- * 单例模式,获取动态类加载器的实例。
- */
- @Getter
- private static DynamicClassLoader instance = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
-
- /**
- * 清理并重新初始化动态类加载器。
- * 该方法旨在重新配置动态类加载器,以便它可以继续加载新的类,而不会受到之前加载类的影响。
- * 这是通过关闭当前的动态类加载器实例并创建一个新的实例来实现的。
- * 在这个过程中,它使用当前线程的上下文类加载器作为新实例的基础。
- * 如果在关闭当前实例或创建新实例的过程中发生IO异常,将会抛出一个LoaderRuntimeException。
- */
- public static void clear() {
- try {
- // 关闭当前的动态类加载器实例
- instance.close();
- // 创建一个新的动态类加载器实例,基于当前线程的上下文类加载器
- instance = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
- } catch (IOException e) {
- // 抛出运行时异常,带有IO异常的信息和根异常
- throw new LoaderRuntimeException(e.getMessage(), e);
- }
- }
-
- /**
- * 添加URL到类加载器的搜索路径。
- *
- * @param url 要添加的URL
- */
- @Override
- public void addURL(URL url) {
- super.addURL(url);
- }
-
- /**
- * 将类的字节码添加到类映射中,以供动态加载。
- *
- * @param fullClassName 类的完全限定名
- * @param classData 类的字节码数据
- */
- public void addClassMap(String fullClassName, byte[] classData) {
- classMap.put(fullClassName, defineClass(fullClassName, classData, 0, classData.length));
- }
-
- /**
- * 根据类的完全限定名查找并加载类。
- * 首先尝试从类映射中加载类,如果未找到,则调用父类加载器的findClass方法。
- *
- * @param fullClassName 类的完全限定名
- * @return 加载的Class对象
- * @throws ClassNotFoundException 如果类未找到
- */
- @Override
- protected Class> findClass(String fullClassName) throws ClassNotFoundException {
- // 尝试从类映射中加载类
- Class> clazz = classMap.get(fullClassName);
- // 如果类在映射中不存在,则记录debug信息
- if (clazz == null) log.debug("[动态编译]classMap未找到类:" + fullClassName);
- else return clazz; // 如果类在classMap中找到,则直接返回
- // 如果classMap中未找到类,则调用父ClassLoader的findClass方法尝试加载类
- return super.findClass(fullClassName);
- }
-}
-
diff --git a/src/main/java/cn/wubo/loader/util/class_loader/JavaBuilder.java b/src/main/java/cn/wubo/loader/util/class_loader/JavaBuilder.java
deleted file mode 100644
index 85d77096303672b1e8596266cd6b1bb8ea94bb0f..0000000000000000000000000000000000000000
--- a/src/main/java/cn/wubo/loader/util/class_loader/JavaBuilder.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package cn.wubo.loader.util.class_loader;
-
-import cn.wubo.loader.util.exception.LoaderRuntimeException;
-import lombok.extern.slf4j.Slf4j;
-
-import javax.tools.*;
-import java.io.Writer;
-import java.util.Collections;
-import java.util.Map;
-
-@Slf4j
-public class JavaBuilder {
- // Java编译器实例
- private JavaCompiler compiler;
- // 用于收集编译过程中的诊断信息
- private DiagnosticCollector diagnosticCollector;
- // 编译结果输出的writer
- private Writer out;
- // 内存文件管理器,用于在内存中管理编译后的类文件
- private MemFileManager memFileManager;
- // 编译选项
- private Iterable options;
- // 需要编译的类名集合
- private Iterable classes;
-
- /**
- * JavaBuilder的构造函数。
- * 初始化Java编译器和相关组件。
- */
- public JavaBuilder() {
- this.compiler = ToolProvider.getSystemJavaCompiler();
- this.diagnosticCollector = new DiagnosticCollector<>();
- this.memFileManager = new MemFileManager(compiler.getStandardFileManager(diagnosticCollector, null, null));
- }
-
- /**
- * 静态方法,用于创建JavaBuilder实例。
- * 这是一种常见的Builder模式,用于实例化对象。
- *
- * @return JavaBuilder的实例
- */
- public static JavaBuilder builder() {
- return new JavaBuilder();
- }
-
- /**
- * 编译给定的Java源代码。
- *
- * @param javaSourceCode Java源代码字符串
- * @param fullClassName 完全限定类名
- * @return 当前JavaBuilder实例,支持方法链调用
- */
- public JavaBuilder compiler(String javaSourceCode, String fullClassName) {
- log.debug("开始执行编译");
- JavaMemSource file = new JavaMemSource(fullClassName, javaSourceCode);
- Iterable extends JavaFileObject> compilationUnits = Collections.singletonList(file);
- log.debug("获取编译任务");
- JavaCompiler.CompilationTask task = compiler.getTask(out, memFileManager, diagnosticCollector, options, classes, compilationUnits);
- log.debug("执行编译");
- boolean result = task.call();
- if (!result) {
- String errorMessage = diagnosticCollector.getDiagnostics().stream().map(Object::toString).reduce("", (acc, x) -> acc + "\r\n" + x);
- log.debug("编译失败: {}", errorMessage);
- throw new LoaderRuntimeException("编译失败: " + errorMessage);
- }
- log.debug("编译成功");
- return this;
- }
-
- /**
- * 获取编译后的类的映射。
- * 这个映射将类名映射到内存中的类对象,可以用于后续的类加载和使用。
- *
- * @return 编译后的类的映射
- */
- public Map getJavaMemClassMap() {
- return memFileManager.getJavaMemClassMap();
- }
-}
-
diff --git a/src/main/java/cn/wubo/loader/util/class_loader/JavaMemClass.java b/src/main/java/cn/wubo/loader/util/class_loader/JavaMemClass.java
deleted file mode 100644
index 7eb0cf4fdba82f617d929188d351a9b4c1d36953..0000000000000000000000000000000000000000
--- a/src/main/java/cn/wubo/loader/util/class_loader/JavaMemClass.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package cn.wubo.loader.util.class_loader;
-
-import javax.tools.SimpleJavaFileObject;
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.net.URI;
-
-/**
- * JavaMemClass 是为了在内存中处理Java类文件而设计的。
- * 它继承自SimpleJavaFileObject,用于表示类文件的内容。
- */
-public class JavaMemClass extends SimpleJavaFileObject {
-
- /**
- * 用于存储类文件字节码的 ByteArrayOutputStream。
- */
- protected final ByteArrayOutputStream classByteArrayOutputStream = new ByteArrayOutputStream();
-
- /**
- * 构造函数初始化JavaMemClass对象。
- *
- * @param name 类的全限定名,使用点(.)分隔。
- * @param kind 类文件的类型,例如SOURCE或CLASS。
- */
- public JavaMemClass(String name, Kind kind) {
- super(URI.create("string:///" + name.replace('.', '/')
- + kind.extension), kind);
- }
-
- /**
- * 获取类文件的字节码。
- *
- * @return 类文件的字节码数组。
- */
- public byte[] getBytes() {
- return classByteArrayOutputStream.toByteArray();
- }
-
- /**
- * 打开一个输出流,用于写入类文件的内容。
- *
- * @return 一个ByteArrayOutputStream,用于写入类文件的字节码。
- */
- @Override
- public OutputStream openOutputStream() {
- return classByteArrayOutputStream;
- }
-}
-
diff --git a/src/main/java/cn/wubo/loader/util/class_loader/JavaMemSource.java b/src/main/java/cn/wubo/loader/util/class_loader/JavaMemSource.java
deleted file mode 100644
index 0f4623c8e265fb13528175a3ea28fa4abe902e13..0000000000000000000000000000000000000000
--- a/src/main/java/cn/wubo/loader/util/class_loader/JavaMemSource.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package cn.wubo.loader.util.class_loader;
-
-import javax.tools.SimpleJavaFileObject;
-import java.net.URI;
-
-/**
- * JavaMemSource类继承自SimpleJavaFileObject,用于在内存中表示Java源代码。
- * 该类的主要作用是提供一种方式来存储和访问Java源代码字符串,而不需要将源代码写入到实际的文件中。
- */
-public class JavaMemSource extends SimpleJavaFileObject{
-
- /**
- * 存储Java源代码的字符串。
- */
- private String javaSourceCode;
-
- /**
- * 构造函数初始化JavaMemSource对象。
- *
- * @param name Java源文件的全限定名,使用'.'作为包名的分隔符。
- * @param javaSourceCode Java源代码的字符串表示。
- */
- public JavaMemSource(String name, String javaSourceCode) {
- super(URI.create("string:///" + name.replace('.', '/')+ Kind.SOURCE.extension), Kind.SOURCE);
- this.javaSourceCode = javaSourceCode;
- }
-
- /**
- * 获取Java源代码的字符序列。
- *
- * @param ignoreEncodingErrors 是否忽略编码错误。该参数在此实现中未使用,因为源代码以字符串形式存储。
- * @return 返回Java源代码的字符序列。
- */
- @Override
- public CharSequence getCharContent(boolean ignoreEncodingErrors) {
- return javaSourceCode;
- }
-}
-
diff --git a/src/main/java/cn/wubo/loader/util/class_loader/MemFileManager.java b/src/main/java/cn/wubo/loader/util/class_loader/MemFileManager.java
deleted file mode 100644
index c051502b3d6f838ff6be6adf252ecdd56846be6b..0000000000000000000000000000000000000000
--- a/src/main/java/cn/wubo/loader/util/class_loader/MemFileManager.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package cn.wubo.loader.util.class_loader;
-
-import javax.tools.FileObject;
-import javax.tools.ForwardingJavaFileManager;
-import javax.tools.JavaFileManager;
-import javax.tools.JavaFileObject;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 在内存中管理编译后Java类的文件管理器。
- * 该类通过继承ForwardingJavaFileManager,实现了一个内存中的Java类管理机制,
- * 主要用于在不将类文件写入磁盘的情况下,存储和管理编译后的Java类。
- */
-public class MemFileManager extends ForwardingJavaFileManager {
-
- /**
- * 用于存储编译后的Java类的内存映射。
- * 键为类名,值为JavaMemClass对象,后者包含类的字节码和其他元数据。
- */
- private Map javaMemClassMap = new HashMap<>();
-
- /**
- * 构造函数,初始化MemFileManager。
- *
- * @param fileManager 基础文件管理器,通常是一个与文件系统交互的文件管理器。
- */
- protected MemFileManager(JavaFileManager fileManager) {
- super(fileManager);
- }
-
- /**
- * 重写getJavaFileForOutput方法,用于在内存中创建并返回一个新的JavaFileObject。
- * 这个方法是编译器在需要写入.class文件时调用的,我们在这里拦截这个调用,
- * 并将.class文件的内容存储在JavaMemClass对象中,而不是写入磁盘。
- *
- * @param location 位置标识,用于指示.class文件应该放置的位置,这里忽略,因为我们在内存中管理类。
- * @param className 类的全限定名。
- * @param kind 类文件的类型,例如SOURCE、CLASS等。
- * @param sibling 如果存在,表示与新类文件相邻的现有文件对象。
- * @return JavaMemClass对象,它在内存中代表了.class文件。
- */
- @Override
- public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) {
- JavaMemClass javaMemClass = new JavaMemClass(className, kind);
- javaMemClassMap.put(className, javaMemClass);
- return javaMemClass;
- }
-
- /**
- * 提供对javaMemClassMap的访问,允许外部获取和检查编译后的类。
- *
- * @return 当前内存中所有编译后类的映射。
- */
- public Map getJavaMemClassMap() {
- return javaMemClassMap;
- }
-}
-
diff --git a/src/main/java/cn/wubo/loader/util/exception/LoaderRuntimeException.java b/src/main/java/cn/wubo/loader/util/exception/LoaderRuntimeException.java
deleted file mode 100644
index 2cdfc7ed145b6991583350e3fc562e4c321db351..0000000000000000000000000000000000000000
--- a/src/main/java/cn/wubo/loader/util/exception/LoaderRuntimeException.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package cn.wubo.loader.util.exception;
-
-public class LoaderRuntimeException extends RuntimeException {
- public LoaderRuntimeException(String message) {
- super(message);
- }
-
- public LoaderRuntimeException(String message, Throwable cause) {
- super(message, cause);
- }
-}
diff --git a/src/test/java/LoderUtilsTest.java b/src/test/java/LoderUtilsTest.java
deleted file mode 100644
index 3d21a80b47841d1fe0c1b0bd8cfcf012132599a3..0000000000000000000000000000000000000000
--- a/src/test/java/LoderUtilsTest.java
+++ /dev/null
@@ -1,195 +0,0 @@
-import cn.wubo.loader.util.LoaderUtils;
-import cn.wubo.loader.util.MethodUtils;
-import cn.wubo.loader.util.SpringContextUtils;
-import groovy.lang.GroovyClassLoader;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
-import org.springframework.boot.test.context.SpringBootTest;
-
-import java.io.IOException;
-
-@SpringBootTest(classes = SpringContextUtils.class)
-@AutoConfigureMockMvc
-class LoderUtilsTest {
-
- @Test
- void testClass() {
- String javaSourceCode = """
- package cn.wubo.loader.util;
-
- public class TestClass {
-
- public String testMethod(String name){
- return String.format("Hello,%s!",name);
- }
- }
- """;
- LoaderUtils.compiler(javaSourceCode, "cn.wubo.loader.util.TestClass");
- Class> clazz = LoaderUtils.load("cn.wubo.loader.util.TestClass");
- String str = (String) MethodUtils.invokeClass(clazz, "testMethod", "world");
- Assertions.assertEquals(str, "Hello,world!");
- }
-
- @Test
- void testClassDelay() {
- Class> clazz = LoaderUtils.load("cn.wubo.loader.util.TestClass");
- String str = (String) MethodUtils.invokeClass(clazz, "testMethod", "world");
- Assertions.assertEquals(str, "Hello,world!");
- }
-
- @Test
- void testInnerClass() {
- String javaSourceCode = """
- package cn.wubo.loader.util;
-
- import lombok.AllArgsConstructor;
- import lombok.Data;
- import lombok.NoArgsConstructor;
-
- public class TestClass1 {
-
- public Object testMethod(String name){
- return new User(name);
- }
-
- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- public static class User {
- private String name;
- }
- }
- """;
- LoaderUtils.compiler(javaSourceCode, "cn.wubo.loader.util.TestClass1");
- Class> clazz = LoaderUtils.load("cn.wubo.loader.util.TestClass1");
- Object obj = MethodUtils.invokeClass(clazz, "testMethod", "world");
- Assertions.assertEquals(obj.toString(), "TestClass1.User(name=world)");
- }
-
- @Test
- void testJarClass() {
- LoaderUtils.addJarPath("./hutool-all-5.8.29.jar");
- Class> clazz = LoaderUtils.load("cn.hutool.core.util.IdUtil");
- String str = (String) MethodUtils.invokeClass(clazz, "randomUUID");
- Assertions.assertFalse(str.isEmpty());
- }
-
- @Test
- void testBean() {
- String javaSourceCode = """
- package cn.wubo.loader.util;
-
- public class TestClass2 {
-
- public String testMethod(String name){
- return String.format("Hello,%s!",name);
- }
- }
- """;
- LoaderUtils.compiler(javaSourceCode, "cn.wubo.loader.util.TestClass2");
- Class> clazz = LoaderUtils.load("cn.wubo.loader.util.TestClass2");
- String beanName = LoaderUtils.registerSingleton(clazz);
- String str = MethodUtils.invokeBean(beanName, "testMethod", "world");
- Assertions.assertEquals(str, "Hello,world!");
- }
-
- @Test
- void testBeans() {
- String javaSourceCode = """
- package cn.wubo.loader.util;
-
- public class TestClass3 {
-
- public String testMethod(String name){
- return String.format("Hello,%s!",name);
- }
- }
- """;
-
- LoaderUtils.compiler(javaSourceCode, "cn.wubo.loader.util.TestClass3");
- Class> clazz = LoaderUtils.load("cn.wubo.loader.util.TestClass3");
- String beanName = LoaderUtils.registerSingleton(clazz);
- Assertions.assertEquals(beanName, "testClass3");
-
- String javaSourceCode2 = """
- package cn.wubo.loader.util;
-
- import cn.wubo.loader.util.MethodUtils;
-
- public class TestClass4 {
-
- public String testMethod(String name) {
- return MethodUtils.invokeBean("testClass3", "testMethod", "world");
- }
- }
- """;
- LoaderUtils.compiler(javaSourceCode2, "cn.wubo.loader.util.TestClass4");
- Class> clazz2 = LoaderUtils.load("cn.wubo.loader.util.TestClass4");
- String beanName2 = LoaderUtils.registerSingleton(clazz2);
- Assertions.assertEquals(beanName2, "testClass4");
- String str2 = MethodUtils.invokeBean(beanName2, "testMethod", "world");
- Assertions.assertEquals(str2, "Hello,world!");
- }
-
- @Test
- void testGroovy() {
- String javaSourceCode = """
- package cn.wubo.loader.util;
-
- public class TestClass5 {
-
- public String testMethod(String name){
- return String.format("Hello,%s!",name);
- }
- }
- """;
- try (GroovyClassLoader groovyClassLoader = new GroovyClassLoader()) {
- groovyClassLoader.parseClass(javaSourceCode);
- Class> clazz = groovyClassLoader.parseClass(javaSourceCode);
- String str = (String) MethodUtils.invokeClass(clazz, "testMethod", "world");
- Assertions.assertEquals(str, "Hello,world!");
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Test
- void testAspect() {
- String javaSourceCode = """
- package cn.wubo.loader.util;
-
- public class TestClass6 {
-
- public String testMethod(String name){
- return String.format("Hello,%s!",name);
- }
- }
- """;
- LoaderUtils.compiler(javaSourceCode, "cn.wubo.loader.util.TestClass6");
- Class> clazz = LoaderUtils.load("cn.wubo.loader.util.TestClass6");
- try {
- Object obj = MethodUtils.proxy(clazz.newInstance());
- String str = MethodUtils.invokeClass(obj, "testMethod", "world");
- } catch (InstantiationException | IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Test
- void testClassOnce() {
- String javaSourceCode = """
- package cn.wubo.loader.util;
-
- public class TestClass7 {
-
- public String testMethod(String name){
- return String.format("Hello,%s!",name);
- }
- }
- """;
- Class> clazz = LoaderUtils.compilerOnce(javaSourceCode, "cn.wubo.loader.util.TestClass7");
- String str = (String) MethodUtils.invokeClass(clazz, "testMethod", "world");
- Assertions.assertEquals(str, "Hello,world!");
- }
-}
diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml
deleted file mode 100644
index 5e107958a45be527f7bda13e740ad98dc5e19492..0000000000000000000000000000000000000000
--- a/src/test/resources/application.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-logging:
- level:
- root: debug