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

 

posted @ 2023-07-13 18:54  zslm___  阅读(56)  评论(0编辑  收藏  举报