Skip to main content
@Export 用于把 Java 方法桥接为 Fluxon 扩展函数(target::method(...)),避免手写注册样板代码。 底层由 ExportRegistry 扫描导出类并生成 ClassBridge(字节码桥接器),实现:
  • 无反射调用
  • 统一的参数类型校验
核心代码位于 core/src/main/java/org/tabooproject/fluxon/runtime/java,主要包括:
  • ExportRegistry
  • ExportMethod
  • ClassBridge
  • ExportBytecodeGenerator

快速上手

最小步骤:提供 target 实例注册导出类创建 Environment 并执行脚本
import org.tabooproject.fluxon.Fluxon;
import org.tabooproject.fluxon.runtime.Environment;
import org.tabooproject.fluxon.runtime.FluxonRuntime;
import org.tabooproject.fluxon.runtime.java.Export;

public final class HashObject {
    public static final HashObject INSTANCE = new HashObject();

    @Export
    public String md5(String input) { /* ... */ return input; }
}

FluxonRuntime runtime = FluxonRuntime.getInstance();
runtime.registerVariable("hash", HashObject.INSTANCE);
runtime.getExportRegistry().registerClass(HashObject.class, "fs:crypto");

Environment env = runtime.newEnvironment();
Object out = Fluxon.eval("import 'fs:crypto'\\nhash::md5('text')", env);
如果你更喜欢“对象工厂”风格,可以注册一个 0 参函数返回实例(例如内置 fs:crypto:hash()),再用 hash::md5(...) 调用。

注册流程

  1. registerClass(clazz, namespace) 扫描 @Export 方法。
  2. 方法名经 StringUtils.transformMethodName 处理(例如 getNow -> now);若与其他原始方法名冲突会回退到原名。
  3. ExportBytecodeGenerator.generateClassBridge(...) 为整类生成 ClassBridge,用于无反射调用。
  4. 参数处理:基于 @Optional 计算支持的参数数量列表(如 [1, 2])。
  5. @Export(async = true)@Export(sync = true) 选择注册为异步扩展 / 主线程扩展 / 普通扩展。

签名与类型校验

  • 调用前使用 Intrinsics.checkArgumentTypes(...) 验证实参类型,确保与 Java 方法签名兼容。
  • 返回值直接透传到脚本;如需转换可在方法内使用 Coerce(见运行时标准库)。

异步与主线程

@Export 支持在注解层声明线程语义:
  • @Export(async = true):注册为异步扩展,调用返回 Future/CompletableFuture,脚本侧通常用 await 等待。
  • @Export(sync = true):注册为主线程扩展,调用会被派发到 FluxonRuntime#setPrimaryThreadExecutor(...) 指定的执行器。

仅注册部分方法

Method method = HashObject.class.getDeclaredMethod("md5", String.class);
ExportMethod exportMethod = new ExportMethod(method, "md5");
runtime.getExportRegistry().registerClassMethods(HashObject.class, "fs:crypto", new ExportMethod[]{exportMethod});
适用于重命名、只导出少数方法或需要绕开默认命名转换的场景。

调试清单

  • FluxonRuntime#getExtensionFunctions() / Environment#getRootExtensionFunctions():查看类型到扩展函数的映射。
  • import 是否缺失:带命名空间的扩展需要脚本 import 'namespace'(如 fs:crypto)。
  • target 是否正确:扩展函数依赖 target 的宿主类型;target 为 null 或类型不匹配会导致“找不到函数”或调用失败。
  • 新增导出未生效:检查是否重建了 Environment(刷新缓存/派发表)。 并在需要时重跑 ./gradlew :core:dumpFluxonCatalog 同步目录。

相关链接