2013-06-12 23 views
5

jestem zaznajomiony z normalnych porywające zamknięć jak teGroovy Zamknięcie wyjaśnienie

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

printSum(5,7) // 12 

Jednak natknąłem kod z SpringWS plugin, że mają czas ciężko zrozumieć:

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) 
} 

Rozumiem, że powyżej jest zamknięciem.

To jest używany tak:

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") 
      } 
     } 
    } 

jeśli serviceURL jest przekazywane w to gdzie jest ładunek?

Czy ktoś może wyjaśnić ten fragment w szczegółach?

+0

to wygląda ładowność jest wstrzykiwany przez wtyczkę z pewnego rodzaju metoda przechwytywania. – moskiteau

+0

Wygląda na to, że rzeczy w nawiasach klamrowych są ładunkiem ("HolidayRequest"). Być może Groovy ma trochę cukru syntaktycznego, który pozwala w ten sposób określić argumenty funkcji?Spróbuj przetestować go, wywołując 'printSum (5) {7}' lub coś podobnego do tego. – rliu

Odpowiedz

4

W powyższej implementacji withEndpointRequest jest zamknięciem, które przyjmuje dwa parametry.

withEndpointRequest(String serviceUrl, Closure payload).

Kiedy używasz withEndpointRequest z klientem, jesteś rzeczywiście robi

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) 

Powyższy został wykonany groovier deklarując inline zamknięcia z withEndpointRequest. Powyższe można również zapisać jako

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") 
      } 
     } 
    }) 

która jest mniej gadatliwe. Wreszcie, może być usprawnione i bardziej groovier pisząc jako

def response = withEndpointRequest(serviceURL) { 
     HolidayRequest(xmlns: namespace) { 
      Holiday { 
       StartDate("2006-07-03") 
       EndDate("2006-07-07") 
      } 
      Employee { 
       Number("42") 
       FirstName("Russ") 
       LastName("Miles") 
      } 
     } 
    } 

jeden punkt, aby pamiętać, jest to, że Closure payload to ostatni parametr.

Teraz należy zauważyć, że zamknięcie (payload) nie jest wywoływane, dopóki nie zostanie wywołane payload.call(), jak wspomniano w pytaniu w wtyczce SpringWS.

Spójrz na Closures as Method Arguments.

Mam nadzieję, że udało mi się przekazać to, co chciałeś zrozumieć. :)

0

Poniższy snipet, opublikowany here, zawiera przegląd kilku opcji stosowanych w celu przekazania zamknięcia do metody.

Metoda z dwoma argumentami. Ostatni argument to zamknięcie.

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

Zdefiniuj zamknięcie.

def assertJava = { 
    it == 'Java' 
} 

sposoby zabicia zamknięcie metody

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' 
// }