java代码片段执行

我发现 XXL-JOB 有 GLUE 功能,粘合了多种语言。
在这里插入图片描述

1、引入 maven 依赖

1
2
3
4
5
6
<!-- groovy-all -->
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>3.0.10</version>
</dependency>

2、自测一版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

// 2022-09-15 14:40 测试 String Java 代码 -> 对象
public static void main1(String[] args) throws Exception {
String code = "package com.xxl.job.service.handler;\n" +
"\n" +
"import com.xxl.job.core.context.XxlJobHelper;\n" +
"import com.xxl.job.core.handler.IJobHandler;\n" +
"\n" +
"public class DemoGlueJobHandler extends IJobHandler {\n" +
"\n" +
"\t@Override\n" +
"\tpublic void execute() throws Exception {\n" +
" System.out.println(\"abc\");\n" +
"\t}\n" +
"\n" +
"}\n";
IJobHandler handler = GlueFactory.getInstance().loadNewInstance(code);
handler.execute();
}


// 2022-09-15 14:42 测试 自定义 Java 代码 -> 反射调用方法
public static void main(String[] args) throws Exception {
String code = " package com.xxl.job.service.handler;\n" +
" \n" +
" import com.xxl.job.core.context.XxlJobHelper;\n" +
" import com.xxl.job.core.handler.IJobHandler;\n" +
" \n" +
" public class A {\n" +
" \n" +
" public String b() throws Exception {\n" +
" System.out.println(\"abc\");\n" +
" return \"bbb\";\n" +
" }\n" +
" \n" +
" }";

GroovyClassLoader gcl = new GroovyClassLoader();
Class<?> clazz = gcl.parseClass(code);
Object a = clazz.newInstance();
Method b = clazz.getDeclaredMethod("b");
Object bbb = b.invoke(a);
}

3、这里放出一下 XXL-JOB 2.3.1 中使用到 GroovyClassLoader 的源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package com.xxl.job.core.glue;

import com.xxl.job.core.glue.impl.SpringGlueFactory;
import com.xxl.job.core.handler.IJobHandler;
import groovy.lang.GroovyClassLoader;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
* glue factory, product class/object by name
*
* @author xuxueli 2016-1-2 20:02:27
*/
public class GlueFactory {


private static GlueFactory glueFactory = new GlueFactory();
public static GlueFactory getInstance(){
return glueFactory;
}
public static void refreshInstance(int type){
if (type == 0) {
glueFactory = new GlueFactory();
} else if (type == 1) {
glueFactory = new SpringGlueFactory();
}
}


/**
* groovy class loader
*/
private GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
private ConcurrentMap<String, Class<?>> CLASS_CACHE = new ConcurrentHashMap<>();

/**
* load new instance, prototype
*
* @param codeSource
* @return
* @throws Exception
*/
public IJobHandler loadNewInstance(String codeSource) throws Exception{
if (codeSource!=null && codeSource.trim().length()>0) {
Class<?> clazz = getCodeSourceClass(codeSource);
if (clazz != null) {
Object instance = clazz.newInstance();
if (instance!=null) {
if (instance instanceof IJobHandler) {
this.injectService(instance);
return (IJobHandler) instance;
} else {
throw new IllegalArgumentException(">>>>>>>>>>> xxl-glue, loadNewInstance error, "
+ "cannot convert from instance["+ instance.getClass() +"] to IJobHandler");
}
}
}
}
throw new IllegalArgumentException(">>>>>>>>>>> xxl-glue, loadNewInstance error, instance is null");
}
private Class<?> getCodeSourceClass(String codeSource){
try {
// md5
byte[] md5 = MessageDigest.getInstance("MD5").digest(codeSource.getBytes());
String md5Str = new BigInteger(1, md5).toString(16);

Class<?> clazz = CLASS_CACHE.get(md5Str);
if(clazz == null){
clazz = groovyClassLoader.parseClass(codeSource);
CLASS_CACHE.putIfAbsent(md5Str, clazz);
}
return clazz;
} catch (Exception e) {
return groovyClassLoader.parseClass(codeSource);
}
}

/**
* inject service of bean field
*
* @param instance
*/
public void injectService(Object instance) {
// do something
}

}