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"; } }