Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 处理多个代理_Java_Groovy_Delegates - Fatal编程技术网

Java 处理多个代理

Java 处理多个代理,java,groovy,delegates,Java,Groovy,Delegates,我有一个java应用程序,我想为它添加一个扩展来执行groovy脚本。到目前为止,解析、编译和执行都不是问题 出于简化的原因,我希望groovy语法尽可能简单(例如,不需要OO技能)。此外,groovy脚本应该能够访问由java类初始化的库函数。这是@代理发挥作用的部分 目前,我提出了两种不同的解决方案,但并不完全满足于我: GroovyService.java MyService.java 解决方案#1-为每个委托方法定义一个方法快捷方式 ServicesFacade.java GroovyS

我有一个java应用程序,我想为它添加一个扩展来执行groovy脚本。到目前为止,解析、编译和执行都不是问题

出于简化的原因,我希望groovy语法尽可能简单(例如,不需要OO技能)。此外,groovy脚本应该能够访问由java类初始化的库函数。这是
@代理
发挥作用的部分

目前,我提出了两种不同的解决方案,但并不完全满足于我:

GroovyService.java

MyService.java

解决方案#1-为每个委托方法定义一个方法快捷方式

ServicesFacade.java

GroovyScript.groovy

带有方法快捷方式的代码部分可以在从groovy文件内容读取的字符串结果之前。如果没有捷径,它将满足我的期望,但我正在寻找一个解决方案,我不必跟踪所有的捷径

解决方案#2-使用服务类型和方法通配符访问列表

ServicesFacade.java

此解决方案的优点是,我可以为任何服务(services*)使用固定的成员名称,但我对其语法印象不深

groovy脚本的使用方式如下:

CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
compilerConfiguration.setScriptBaseClass(DelegatingScript.class.getName());
GroovyShell groovyShell = new GroovyShell(compilerConfiguration);
DelegatingScript script = (DelegatingScript) groovyShell.parse(fileContent);

if (script != null) {
  script.setDelegate(ServicesFacade.INSTANCE);
  scripts.add(script);
}
/* ... */
scripts.forEach(s -> {
  s.run();
});
import groovy.lang.Binding;
import groovy.lang.MetaClass;
import groovy.lang.MissingMethodException;

import org.codehaus.groovy.runtime.InvokerHelper;

import java.util.HashMap;
import java.util.Map;


public abstract class MultiDelegatingScript extends groovy.lang.Script {

  private final Map<Object, MetaClass> delegateMap = new HashMap<>();

  protected MultiDelegatingScript() {
    super();
  }

  protected MultiDelegatingScript(Binding binding) {
    super(binding);
  }

  public void setDelegate(Object delegate) {
    this.delegateMap.put(delegate, InvokerHelper.getMetaClass(delegate.getClass()));
  }

  @Override
  public Object invokeMethod(String name, Object args) {
    for (Map.Entry<Object, MetaClass> delegate : this.delegateMap.entrySet()) {
      try {
        // Try to invoke the delegating method
        return delegate.getValue().invokeMethod(delegate.getKey(), name, args);
      } catch (MissingMethodException mme) {
        // Method not found in delegating object -> try the next one
        continue;
      }
    }

    // No delegating method found -> invoke super class method for further handling
    return super.invokeMethod(name, args);
  }

}

有没有更好的方法来实现委托方法的直接方法调用?

我提出了一个很好的解决方案,其中我编写了一个类似于的类。情况如下:

CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
compilerConfiguration.setScriptBaseClass(DelegatingScript.class.getName());
GroovyShell groovyShell = new GroovyShell(compilerConfiguration);
DelegatingScript script = (DelegatingScript) groovyShell.parse(fileContent);

if (script != null) {
  script.setDelegate(ServicesFacade.INSTANCE);
  scripts.add(script);
}
/* ... */
scripts.forEach(s -> {
  s.run();
});
import groovy.lang.Binding;
import groovy.lang.MetaClass;
import groovy.lang.MissingMethodException;

import org.codehaus.groovy.runtime.InvokerHelper;

import java.util.HashMap;
import java.util.Map;


public abstract class MultiDelegatingScript extends groovy.lang.Script {

  private final Map<Object, MetaClass> delegateMap = new HashMap<>();

  protected MultiDelegatingScript() {
    super();
  }

  protected MultiDelegatingScript(Binding binding) {
    super(binding);
  }

  public void setDelegate(Object delegate) {
    this.delegateMap.put(delegate, InvokerHelper.getMetaClass(delegate.getClass()));
  }

  @Override
  public Object invokeMethod(String name, Object args) {
    for (Map.Entry<Object, MetaClass> delegate : this.delegateMap.entrySet()) {
      try {
        // Try to invoke the delegating method
        return delegate.getValue().invokeMethod(delegate.getKey(), name, args);
      } catch (MissingMethodException mme) {
        // Method not found in delegating object -> try the next one
        continue;
      }
    }

    // No delegating method found -> invoke super class method for further handling
    return super.invokeMethod(name, args);
  }

}
导入groovy.lang.Binding;
导入groovy.lang.MetaClass;
导入groovy.lang.MissingMethodException;
导入org.codehaus.groovy.runtime.InvokerHelper;
导入java.util.HashMap;
导入java.util.Map;
公共抽象类MultiDelegatingScript扩展了groovy.lang.Script{
私有最终映射delegateMap=newhashmap();
受保护的MultiDelegatingScript(){
超级();
}
受保护的MultiDelegatingScript(绑定){
超级(绑定);
}
公共无效集合委托(对象委托){
this.delegateMap.put(委托,InvokerHelper.getMetaClass(delegate.getClass());
}
@凌驾
公共对象调用方法(字符串名称、对象参数){
对于(Map.Entry委托:this.delegateMap.entrySet()){
试一试{
//尝试调用委派方法
返回delegate.getValue().invokeMethod(delegate.getKey(),name,args);
}捕获(丢失方法异常mme){
//在委派对象->尝试下一个中找不到方法
继续;
}
}
//找不到委派方法->调用超类方法进行进一步处理
返回super.invokeMethod(名称、参数);
}
}
使用这个类而不是DelegatingScript将完全满足我的期望

public class ServicesFacade {

  public static final ServicesFacade INSTANCE = new ServicesFacade();

  @Delegate private final List<GroovyService> services = new ArrayList<>();

  private ServicesFacade() { 
    this.services.add(MyService.INSTANCE);
  }

  public void addService(GroovyService service) {
    this.services.add(service);
  }

}
if (services*.method1()) {
  services*.method2()
}
CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
compilerConfiguration.setScriptBaseClass(DelegatingScript.class.getName());
GroovyShell groovyShell = new GroovyShell(compilerConfiguration);
DelegatingScript script = (DelegatingScript) groovyShell.parse(fileContent);

if (script != null) {
  script.setDelegate(ServicesFacade.INSTANCE);
  scripts.add(script);
}
/* ... */
scripts.forEach(s -> {
  s.run();
});
import groovy.lang.Binding;
import groovy.lang.MetaClass;
import groovy.lang.MissingMethodException;

import org.codehaus.groovy.runtime.InvokerHelper;

import java.util.HashMap;
import java.util.Map;


public abstract class MultiDelegatingScript extends groovy.lang.Script {

  private final Map<Object, MetaClass> delegateMap = new HashMap<>();

  protected MultiDelegatingScript() {
    super();
  }

  protected MultiDelegatingScript(Binding binding) {
    super(binding);
  }

  public void setDelegate(Object delegate) {
    this.delegateMap.put(delegate, InvokerHelper.getMetaClass(delegate.getClass()));
  }

  @Override
  public Object invokeMethod(String name, Object args) {
    for (Map.Entry<Object, MetaClass> delegate : this.delegateMap.entrySet()) {
      try {
        // Try to invoke the delegating method
        return delegate.getValue().invokeMethod(delegate.getKey(), name, args);
      } catch (MissingMethodException mme) {
        // Method not found in delegating object -> try the next one
        continue;
      }
    }

    // No delegating method found -> invoke super class method for further handling
    return super.invokeMethod(name, args);
  }

}