Groovy结束异常与异常抛出不同

时间:2011-08-18 17:42:45

标签: exception groovy

我在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()。在脚本中找不到它,它将调用methodMissingmethod()然后从myDelegate调用testDelegatepropertyMissing依次调用闭包,将委托设置为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项目。我宁愿知道这个的根本原因,而不仅仅是删除一两行,看看它是否有效而不理解为什么。

1 个答案:

答案 0 :(得分:1)

我认为这是本质上发生的事情:使用委托优先解析策略,Groovy运行时首先尝试访问a上的属性myDelegate,这会导致MissingPropertyException,因为没有这样的财产存在。然后它会尝试propertyMissing,这会导致MyOwnException被抛出。最终,运行时放弃并重新抛出遇到的第一个异常(设计决策),恰好是MissingPropertyException

使用所有者优先解决策略,首先咨询propertyMissing,因此MyOwnException最终会被重新播放。

查看下面的堆栈跟踪和源代码应该提供更多证据。