首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何集成beanshell

如何集成beanshell
EN

Stack Overflow用户
提问于 2014-12-06 19:35:44
回答 3查看 362关注 0票数 10

我正在用java开发一个基于组件的游戏引擎,现在,当我对组件进行更改时,我需要重新构建并重新启动编辑器,以使更改生效(或者,如果应用程序在调试模式下运行,我可以使用一些有限的热代码注入)。

我正在寻找一种方法,允许用户修改组件的源代码并重新加载它们,而不必重新启动应用程序(可能只需退出并进入游戏模式)。另外,我需要的一个重要特性是,最终导出的代码应该是本机Java代码(所以在最终结果中不应该使用解释器)。

你能给我一些关于如何在项目中集成beanshell解释器的建议吗?我可以手动监控源文件夹的变化,并将更新的java类提供给它,但是热交换到底是如何发生的呢?

EN

回答 3

Stack Overflow用户

发布于 2014-12-09 21:24:46

首先,标题有点让人困惑。您不需要集成BeanShell。你真正需要的是:

Java编译器要定义正确的architecture

  • to,请使用编译器
  1. 来处理java类

架构

假设你有一个对象图。有很多对象,引用等,所以用新的实例替换一些实例真的是一项棘手的任务。你可以将动态部分隐藏在“静态”代理后面,而不是解决这个问题。代理将处理所有重新加载的内容(包括源文件夹监控)。

重新加载之前:

重新加载后:

完成此操作后,您可以轻松跟踪更改并在需要时更新动态部分。

Java编译器API

你可以不使用解释型语言,而是使用Java,动态编译并使用'Class.forName()‘加载。由于这种方法已经存在了一段时间,因此有很多不同的例子。

以下是一些详细信息:

票数 4
EN

Stack Overflow用户

发布于 2014-12-15 06:52:47

基本上,您希望实现extensibility或插件设计模式。有多种方法可以实现此场景。

无论您想要哪个组件,都允许其他人重新加载模块,定义一个接口,并将您自己的实现实现为默认实现。例如,这里我试图提供一个每个国家都可以随时实现和加载的HelloInterface,

代码语言:javascript
运行
复制
 public interface HelloInterface {

    public String sayHello(String input);
    ..   
 }

 public class HelloImplDefault implements HelloInterface {

    public String sayHello(String input) {
         return "Hello World";
    }
 }

现在允许用户将插件(自定义实现)文件添加到预先配置的路径中。您可以使用FileSystemWatcher或后台线程来扫描此路径,并尝试编译和加载该文件。

编译java文件:

代码语言:javascript
运行
复制
    private void  compile(List<File> files) throws IOException{


        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
        Iterable<? extends JavaFileObject> compilationUnits = fileManager
            .getJavaFileObjectsFromFiles(files);
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null,
            null, compilationUnits);
        boolean success = task.call();
        fileManager.close();

}

要加载类文件,

代码语言:javascript
运行
复制
private void load(List<File> files) throws MalformedURLException, InstantiationException, IllegalAccessException, ClassNotFoundException{

     ClassLoader cl = Thread.currentThread().getContextClassLoader();

    for(File f: files){
        if(f.getName().endsWith(".class") && !loadedClass.contains(f.getName())){
             URL url = f.toURL();
             URL[] urls = new URL[]{url};
             Object obj = cl.loadClass(f.getName().replace(".class", "")).newInstance();
             if(obj instanceof HelloInterface){
                 HelloProviders.addProvider((HelloInterface)obj);
                 System.out.println("Loaded "+ ((HelloInterface)obj).getProviderName());
             }else{
                 //Add more classes if you want
             }
             loadedClass.add(f.getName());
        }
    }
}

此时,您可以读取自定义实现并将其加载到系统类加载器中。现在你已经准备好出发了。这种方法有安全隐患,你需要从互联网中学习。

我实现了一个示例代码,并发布在github,please take a look上。祝你编码愉快!

票数 0
EN

Stack Overflow用户

发布于 2014-12-15 21:14:08

看看支持live-reloadingtapestry-ioc控制反转容器。

当处于开发模式(tapestry.product- mode =false)时,您可以实时重新加载您的服务。请注意,如果服务接口发生更改,您将需要重新启动。但是,对服务实现的任何更改,只要不改变服务接口,都可以实时重新加载。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27331252

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档