我在Groovy中遇到了一个非常奇怪的行为。当我从脚本中的闭包中抛出异常时,抛出的结束异常是不同的。
以下是代码和详细信息:
public class TestDelegate {
def method(Closure closure) {
closure.setResolveStrategy(Closure.DELEGATE_FIRST);
closure.delegate = this;
closure.call();
}
public static void main(String[] args) {
// Make Script from File
File dslFile = new File("src/Script.dsl");
GroovyShell shell = new GroovyShell();
Script dslScript = shell.parse(dslFile);
TestDelegate myDelegate = new TestDelegate();
dslScript.metaClass.methodMissing = {
// will run method(closure)
String name, arguments ->
myDelegate.invokeMethod(name, arguments);
}
dslScript.metaClass.propertyMissing = {
String name ->
println "Will throw error now!"
throw new MyOwnException("errrrror");
}
dslScript.run();
}
}
class MyOwnException extends Exception {
public MyOwnException(String message) {
super(message);
}
}
Script.dsl:
method {
println a;
}
所以计划是当我在main()
中运行TestDelegate
方法时,它将运行DSL脚本,该脚本调用方法method()
。在脚本中找不到它,它将调用methodMissing
,method()
然后从myDelegate
调用testDelegate
,propertyMissing
依次调用闭包,将委托设置为MyOwnException
。到现在为止还挺好。然后封闭应该尝试打印出“a”,这是未定义的,因此会引发Will throw error now!
Exception in thread "main" groovy.lang.MissingPropertyException: No such property: a for class: TestDelegate
,这将抛出MyOwnException
。
但是,当我运行代码时,我得到以下输出:
MyOwnException
现在,它必须已达到该阻止块,因为它打印出“现在会抛出错误!”它必须抛出MissingPropertyException
!但是在某些地方,closure.setResolveStrategy(Closure.DELEGATE_FIRST)
被转换为TestDelegate#method()
,我不知道为什么。有没有人有任何想法?
P.S。如果我从MyOwnException
删除setResolveStrategy(Closure.DELEGATE_FIRST)
,则代码按预期运行并抛出{{1}}。但我真的需要{{1}}用于我的DSL项目。我宁愿知道这个的根本原因,而不仅仅是删除一两行,看看它是否有效而不理解为什么。
答案 0 :(得分:1)
我认为这是本质上发生的事情:使用委托优先解析策略,Groovy运行时首先尝试访问a
上的属性myDelegate
,这会导致MissingPropertyException
,因为没有这样的财产存在。然后它会尝试propertyMissing
,这会导致MyOwnException
被抛出。最终,运行时放弃并重新抛出遇到的第一个异常(设计决策),恰好是MissingPropertyException
。
使用所有者优先解决策略,首先咨询propertyMissing
,因此MyOwnException
最终会被重新播放。
查看下面的堆栈跟踪和源代码应该提供更多证据。