Groovy Closure说明

时间:2013-06-12 19:26:29

标签: groovy

我熟悉正常的groovy闭包,比如这些

def printSum = {a,b ->
   println a+b
}

printSum(5,7) // 12

但是,我遇到了来自SpringWS插件的代码,我很难理解:

def withEndpointRequest = { url, payload ->
    def writer = new StringWriter()
    def request = new MarkupBuilder(writer)
    payload.delegate = request
    payload.call()
    def webServiceTemplate = new WebServiceTemplate()

    def response = webServiceTemplate.sendToEndpoint(url, writer.toString())
    new XmlSlurper().parseText(response)
}

我知道上面是一个闭包。

它的使用方式如下:

    def namespace = "http://www.myveryimportantcompany.com/hr/schemas"
    def serviceURL = "http://localhost:8080/myapp/services"
    def response = withEndpointRequest(serviceURL) {
        HolidayRequest(xmlns: namespace) {
            Holiday {
                StartDate("2006-07-03")
                EndDate("2006-07-07")
            }
            Employee {
                Number("42")
                FirstName("Russ")
                LastName("Miles")
            }
        }
    }

如果传递serviceURL那么有效载荷在哪里?

有人可以详细解释这个片段吗?

2 个答案:

答案 0 :(得分:4)

在上面的实现中,withEndpointRequest是一个带有两个参数的闭包。

withEndpointRequest(String serviceUrl, Closure payload)

当您从客户端使用withEndpointRequest时,您实际上在做

    def namespace = "http://www.myveryimportantcompany.com/hr/schemas"
    def serviceURL = "http://localhost:8080/myapp/services"
    def payload = {
         HolidayRequest(xmlns: namespace) {
            Holiday {
                StartDate("2006-07-03")
                EndDate("2006-07-07")
            }
            Employee {
                Number("42")
                FirstName("Russ")
                LastName("Miles")
            }
        }
    }
    def response = withEndpointRequest(serviceURL, payload) 

通过声明与withEndpointRequest内联的封闭,上述内容更加流畅。 以上也可以写成

def response = withEndpointRequest(serviceURL, {
        //payload goes here as an inline closure as the second parameter
        HolidayRequest(xmlns: namespace) {
            Holiday {
                StartDate("2006-07-03")
                EndDate("2006-07-07")
            }
            Employee {
                Number("42")
                FirstName("Russ")
                LastName("Miles")
            }
        }
    })

不那么冗长。最后,通过写作

,可以简化它并使其更加流畅
def response = withEndpointRequest(serviceURL) {
        HolidayRequest(xmlns: namespace) {
            Holiday {
                StartDate("2006-07-03")
                EndDate("2006-07-07")
            }
            Employee {
                Number("42")
                FirstName("Russ")
                LastName("Miles")
            }
        }
    }

这里要注意的一点是Closure payload是最后一个参数。

现在,请注意在调用payload之前不会调用闭包(payload.call()),如SpringWS插件中的问题所述。

查看Closures as Method Arguments

我希望我能传达你想要理解的东西。 :)

答案 1 :(得分:0)

以下snipet发布了here,概述了用于将闭包传递给方法的几个选项。

带有两个参数的方法。最后一个参数是一个闭包。

def work(input, cl) {
    cl(input)
}

定义一个闭包。

def assertJava = {
    it == 'Java'
}

将闭包传递给方法的方法

work('Java', assertJava)

work 'Java', assertJava  // No parenthesis.

work('Groovy', {
    assert it == 'Groovy'
})  // Anonymous closure as argument.

work('Groovy') {
    assert it == 'Groovy'
}  // Last argument is closure and can be outside parenthesis. 

work('Groovy')
{
     assert it == 'Groovy'
}  // Opening bracket on new line. If we want a code block (e.g. static initializer) instead of closure we must use ; to separate code.


work 'Groovy', {
    assert it == 'Groovy'
}  // Pay attention, no parenthesis, so comma is needed again!


// Does not work:
//
// Comma between argument list needed:
// work 'Groovy' {
//     assert it == 'Groovy'
// }