Рекомендуемый подход для вызова функций (использовать CompiledScript или нет?)

Я пишу библиотеку, которая предлагает поддержку макросов для выполнения на различных языках, не являющихся Java, на JVM. Подумайте о JavaScript, Ruby и т. Д.

Поэтому я хочу использовать API сценариев JSR-223.

Этот API имеет понятие CompiledScript класс, и я предполагаю, что это будет наилучшим способом предварительной компиляции сценариев во время загрузки и их повторного использования при выполнении.

Это хорошая практика, чтобы проверить, если ScriptEngine это экземпляр Compilable и если так, то используйте CompiledScript подход и в противном случае просто оценить функцию в ScriptEngine сам?

Например (упрощенно):

Invocable invocable;
if (scriptEngine instanceof Compilable) {
    // Compile the code.
    CompiledScript compiledFunction = ((Compilable) scriptEngine).compile(function);
    compiledFunction.eval();
    invocable = (Invocable) compiledFunction.getEngine();
} else {
    // Run the code to load the function into the script engine.
    scriptEngine.eval(function);
    invocable = (Invocable) scriptEngine;
}
Object value = invocable.invokeFunction(resolveFunctionName(name), args);
return value != null ? value.toString() : null;

Есть ли в этом случае польза от использования CompiledScript или это пренебрежимо мало?

Моя фактическая реализация немного более продвинута и имеет отдельный шаблон загрузки и вызова для повторного использования фактической CompiledScript:

public void load(String name, String[] code) {
    if (scriptEngine == null) {
        logger.warn("Cannot load macro '{}' as no script engine was found for '{}'", name, scriptEngineShortName);
    } else {
        // Create a unique function name called the same as the object macro name.
        String function = resolveFunctionCode(name, code);
        try {
            if (scriptEngine instanceof Compilable) {
                // Compile the code.
                CompiledScript compiledFunction = ((Compilable) scriptEngine).compile(function);
                compiledFunction.eval();
                compiledFunctions.put(name, compiledFunction);
            } else {
                // Run the code to load the function into the script engine.
                scriptEngine.eval(function);
            }
        } catch (ScriptException e) {
            logger.error("Error loading code for marco '{}'", name, e);
        }
    }
}

public String call(String name, String[] fields) {
    String result = null;
    if (scriptEngine == null) {
        logger.warn("Cannot call macro '{}' as no script engine was found for '{}'", name, scriptEngineShortName);
    } else {
        try {
            Invocable invocable = null;
            if (scriptEngine instanceof Compilable) {
                if (compiledFunctions.containsKey(name)) {
                    CompiledScript compiledFunction = compiledFunctions.get(name);
                    invocable = (Invocable) compiledFunction.getEngine();
                }
            } else {
                invocable = (Invocable) scriptEngine;
            }
            if (invocable != null) {
                Object value = invocable.invokeFunction(resolveFunctionName(name), rs, fields);
                if (value != null) {
                    result = value.toString();
                }
            } else {
                logger.warn("Cannot call macro '{}' as no function was found", name);
            }
        } catch (ScriptException e) {
            logger.error("Error invoking function for macro '{}'", name, e);
        } catch (NoSuchMethodException e) {
            logger.error("Error invoking function for macro '{}'", name, e);
        }
    }
    return result;
}

0 ответов

Другие вопросы по тегам