# 动态编译加载执行工具 **Repository Path**: mick-zeng/loader-util ## Basic Information - **Project Name**: 动态编译加载执行工具 - **Description**: 在运行期动态加载、编译、执行工具,包括( 1.DynamicBean 动态加载Bean并执行; 2.DynamicClass 动态编译加载Class并执行; 3.DynamicJar 动态加载外部jar到项目中; 4.DynamicGroovy 动态编译加载Groovy并执行; 5.DynamicController 动态编译加载Controller并执行; 6.proxy 动态代理切面; ) - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 24 - **Created**: 2024-01-30 - **Last Updated**: 2024-01-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # loader-util 动态编译、加载、执行工具 [![](https://jitpack.io/v/com.gitee.wb04307201/loader-util.svg)](https://jitpack.io/#com.gitee.wb04307201/loader-util) ## 代码示例 1. 使用[动态编译加载执行工具](https://gitee.com/wb04307201/loader-util)实现的[动态编译加载执行工具示例代码](https://gitee.com/wb04307201/loader-util-test) 2. 使用[动态调度](https://gitee.com/wb04307201/dynamic-schedule-spring-boot-starter)、[消息中间件](https://gitee.com/wb04307201/message-spring-boot-starter)、[动态编译加载执行工具](https://gitee.com/wb04307201/loader-util)、[实体SQL工具类](https://gitee.com/wb04307201/sql-util)实现的[动态编码动态任务调度Demo](https://gitee.com/wb04307201/dynamic-schedule-demo) ## 第一步 增加 JitPack 仓库 ```xml jitpack.io https://jitpack.io ``` ## 第二步 引入jar 1.1.0版本后升级到jdk 17 SpringBoot 3.2.0 ```xml com.gitee.wb04307201 loader-util 1.1.0 ``` ## 第三步 如何使用 ## 1. DynamicBean 动态编译加载Bean并执行 > 使用DynamicBean需要配置@ComponentScan,包括cn.wubo.loader.util.SpringContextUtils文件 ```java @GetMapping(value = "/test/bean") public String testBean(){ String javaSourceCode = "package cn.wubo.loader.util;\n" + "\n" + "public class TestClass {\n" + " \n" + " public String testMethod(String name){\n" + " return String.format(\"Hello,%s!\",name);\n" + " }\n" + "}"; String fullClassName = "cn.wubo.loader.util.TestClass"; String methodName = "testMethod"; String beanName = DynamicBean.init(DynamicClass.init(javaSourceCode,fullClassName)).load(); return (String) MethodUtils.invokeBean(beanName,methodName,"world"); } ``` ## 2. DynamicClass 动态编译加载Class并执行 ```java @GetMapping(value = "/test/class") public String testClass(){ String javaSourceCode = "package cn.wubo.loader.util;\n" + "\n" + "public class TestClass {\n" + " \n" + " public String testMethod(String name){\n" + " return String.format(\"Hello,%s!\",name);\n" + " }\n" + "}"; String fullClassName = "cn.wubo.loader.util.TestClass"; String methodName = "testMethod"; DynamicClass dynamicClass = DynamicClass.init(javaSourceCode, fullClassName).compiler(); Class clasz = dynamicClass.load(); return (String) MethodUtils.invokeClass(clasz, methodName, "world"); } ``` ## 3. DynamicJar 动态加载外部jar并执行 ```java @GetMapping(value = "/test/jar") public String testJar(){ Class clasz = DynamicJar.init("D:\\maven-repository\\repository\\cn\\hutool\\hutool-all\\5.3.2\\hutool-all-5.3.2.jar").load("cn.hutool.core.util.IdUtil"); return (String) MethodUtils.invokeClass(clasz, "randomUUID"); } ``` ## 4. DynamicGroovy 动态编译加载Groovy并执行 ```java @GetMapping(value = "/loadAndInvokeGroovy") public String loadAndInvokeGroovy() { String javaSourceCode = "package cn.wubo.loader.util;\n" + "\n" + "public class TestClass {\n" + " \n" + " public String testMethod(String name){\n" + " return String.format(\"Hello,%s!\",name);\n" + " }\n" + "}"; String methodName = "testMethod"; Class clasz = DynamicGroovy.init(javaSourceCode).load(); return (String) MethodUtils.invokeClass(clasz, methodName, "world"); } ``` ## 5. DynamicController 动态编译加载Controller并执行 ```java @GetMapping(value = "/loadController") public String loadController() { String fullClassName = "cn.wubo.loaderutiltest.DemoController"; String javaSourceCode = "package cn.wubo.loaderutiltest;\n" + "\n" + "import org.springframework.web.bind.annotation.GetMapping;\n" + "import org.springframework.web.bind.annotation.RequestMapping;\n" + "import org.springframework.web.bind.annotation.RequestParam;\n" + "import org.springframework.web.bind.annotation.RestController;\n" + "\n" + "@RestController\n" + "@RequestMapping(value = \"test\")\n" + "public class DemoController {\n" + "\n" + " @GetMapping(value = \"hello\")\n" + " public String testMethod(@RequestParam(value=\"name\") String name) {\n" + " return String.format(\"Hello,%s!\", name);\n" + " }\n" + "}"; return DynamicController.init(DynamicClass.init(javaSourceCode, fullClassName)).load(); } ``` ```http request GET http://localhost:8080/test/hello?name=world Accept: application/json Hello,world! ``` #### 如需在controller种调用其他bean,请使用MethodUtils.invokeBean("demoService", "testMethod", name) ```java @GetMapping(value = "/loadControllerAndBean") public String loadControllerAndBean() { String fullClassName1 = "cn.wubo.loaderutiltest.DemoService"; String javaSourceCode1 = """ package cn.wubo.loaderutiltest; import org.springframework.stereotype.Service; @Service public class DemoService { public String testMethod(String name) { return String.format("Hello,%s!", name); } } """; String beanName = DynamicBean.init(DynamicClass.init(javaSourceCode1, fullClassName1)).load(); String fullClassName2 = "cn.wubo.loaderutiltest.DemoController"; String javaSourceCode2 = """ package cn.wubo.loaderutiltest; import cn.wubo.loader.util.MethodUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(value = "test") public class DemoController { @GetMapping(value = "hello") public String testMethod(@RequestParam(value = "name") String name) { return MethodUtils.invokeBean("demoService", "testMethod", name); } } """; return DynamicController.init(DynamicClass.init(javaSourceCode2, fullClassName2)).load(); } ``` ## 6. proxy 动态代理切面 ```java @GetMapping(value = "/testAspect") public String testAspect() throws InstantiationException, IllegalAccessException { String javaSourceCode = "package cn.wubo.loader.util;\n" + "\n" + "public class TestClass {\n" + " \n" + " public String testMethod(String name){\n" + " return String.format(\"Hello,%s!\",name);\n" + " }\n" + "}"; String fullClassName = "cn.wubo.loader.util.TestClass"; String methodName = "testMethod"; DynamicClass dynamicClass = DynamicClass.init(javaSourceCode, fullClassName).compiler(); Class clasz = dynamicClass.load(); Object obj = MethodUtils.proxy(clasz.newInstance()); return (String) MethodUtils.invokeClass(obj, methodName, "world"); } ``` 输出示例 ```text 2023-04-08 21:22:14.174 INFO 32660 --- [nio-8080-exec-1] cn.wubo.loader.util.aspect.SimpleAspect : SimpleAspect before cn.wubo.loader.util.TestClass testMethod 2023-04-08 21:22:14.175 INFO 32660 --- [nio-8080-exec-1] cn.wubo.loader.util.aspect.SimpleAspect : SimpleAspect after cn.wubo.loader.util.TestClass testMethod 2023-04-08 21:22:14.175 INFO 32660 --- [nio-8080-exec-1] cn.wubo.loader.util.aspect.SimpleAspect : StopWatch 'cn.wubo.loader.util.TestClass testMethod': running time = 65800 ns ``` 可以通过继承IAspect接口实现自定义切面,并通过MethodUtils.proxy(Class clazz, Class aspectClass)方法调用切面