Groovy定义的Class在Spel中使用
@Resource private ICustomFunctionService customFunctionService; @PostConstruct private void init() { LambdaQueryWrapper<CustomFunctionEo> wrapper = Wrappers.lambdaQuery(CustomFunctionEo.class) .eq(CustomFunctionEo::getDr, 0); List<CustomFunctionEo> list = customFunctionService.getInnerService().list(wrapper); try { list.forEach(p -> { String function = p.getFunction(); CustomFunctionFactory.getCodeSourceClass(function); }); SpelParserConfiguration configuration = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, CustomFunctionFactory.GroovyClassLoader); String _spelExpression = "T(com.g2.exchange.biz.service.auth.custom.AbcUtil).sign(null)"; Map<String, Object> context = new HashMap<>(); SpelExpressionParser spelParser = new SpelExpressionParser(configuration); StandardEvaluationContext spelContext = new StandardEvaluationContext(context); // 重要的是下面这行代码, 将classLoader传给Spel spelContext.setTypeLocator(new StandardTypeLocator(CustomFunctionFactory.GroovyClassLoader)); Expression spelExpression = spelParser.parseExpression(_spelExpression); Object v = spelExpression.getValue(spelContext); System.out.println(v); } catch (Exception ex) { ex.printStackTrace(); } }
import groovy.lang.GroovyClassLoader; import java.math.BigInteger; import java.security.MessageDigest; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class CustomFunctionFactory { public static GroovyClassLoader GroovyClassLoader = new GroovyClassLoader(CustomFunctionFactory.class.getClassLoader()); private static ConcurrentMap<String, Class<?>> CUSTOM_CLASS_CACHE = new ConcurrentHashMap<>(); private static ConcurrentMap<String, Object> CUSTOM_CLASS_INSTANCE_CACHE = new ConcurrentHashMap<>(); private static String getKey(String codeSource) { try { byte[] md5 = MessageDigest.getInstance("MD5").digest(codeSource.getBytes()); return new BigInteger(1, md5).toString(16); } catch (Exception ex) { throw new BizException("md5异常"); } } public static <T> T getInstance(String codeSource, Class<T> tClass) { String key = getKey(codeSource); Object instance = CUSTOM_CLASS_INSTANCE_CACHE.get(key); if (instance != null) { return (T) instance; } synchronized (CustomFunctionFactory.class) { instance = CUSTOM_CLASS_INSTANCE_CACHE.get(key); if (instance != null) { return (T) instance; } try { instance = generateInstance(codeSource, tClass); CUSTOM_CLASS_INSTANCE_CACHE.put(key, instance); return (T) instance; } catch (Exception ex) { ex.printStackTrace(); throw new RuntimeException(ex.getMessage()); } } } private static <T> T generateInstance(String codeSource, Class<T> tClass) throws Exception { if (codeSource != null && codeSource.trim().length() > 0) { Class<?> clazz = getCodeSourceClass(codeSource); if (clazz != null) { Object instance = clazz.newInstance(); if (instance != null) { if (tClass.isAssignableFrom(instance.getClass())) { return (T) 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"); } public static synchronized Class<?> getCodeSourceClass(String codeSource) { try { String md5Str = getKey(codeSource); Class<?> clazz = CUSTOM_CLASS_CACHE.get(md5Str); if (clazz == null) { clazz = GroovyClassLoader.parseClass(codeSource); CUSTOM_CLASS_CACHE.putIfAbsent(md5Str, clazz); } return clazz; } catch (Exception e) { return GroovyClassLoader.parseClass(codeSource); } } }
<dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>2.4.19</version> </dependency>
AbcUtil的代码放在数据库里
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; /** * 不要使用,这只是 一个示例 */ public class AbcUtil { private static final Logger log = LoggerFactory.getLogger(AbcUtil.class); public static String sign(String[] args) throws Exception { return "aaa"; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
2016-07-13 ServiceStack.Text 更快的序列化