Date post: | 18-Nov-2014 |
Category: |
Technology |
Upload: | spring-io |
View: | 236 times |
Download: | 2 times |
© 2013 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Metaprogramming With The Groovy Runtime – Part 1 of 2
Jeff Scott Brown@jeffscottbrown
Metaprogramming● What Is It?
– behavior changes at runtime
– capabilities are introduced at runtime
– Wikipedia says...
“Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves)...”
Metaprogramming And Groovy● Groovy Lends Itself Well To Metaprogramming
– dynamic method dispatch
– method/property interception
– create methods at runtime
– JVM supports very dynamic behavior
● much cannot be easily tapped by Java the language
Expando
● Dynamically Expanding Objectdef myExpando = new Expando()
myExpando.favoriteLanguage = 'Groovy'
myExpando.addNumbers = { i, j -> i + j }
assert 'Groovy' == myExpando.favoriteLanguage
assert 100 == myExpando.addNumbers(60, 40)
assert myExpando.foo == null
Runtime Mappings
expando.favoriteLanguage = 'Groovy'// maps to...expando.setProperty('favoriteLanguage', 'Groovy')
expando.favoriteLanguage// maps to...expando.getProperty('favoriteLanguage')
expando.addNumbers(33, 66)// maps to...expando.invokeMethod('addNumbers', [33, 66] as Object[])
Our Own Expando
With Those 3 Simple Methods We Can Create Our Own Version Of Expando In 3 Minutes.
Let's Do That Now. Live Demo...
Closure Delegates● Closures May Be Assigned A “Delegate”● Closures Relay Method Calls To Their
Delegate● Useful For Creating DSLs And Builders● Same Closure May Be Executed In
Different Contexts With Different Delegates
Closure Delegatesdef myClosure = { append('First Line\n') append('Last Line\n')}// will fail because there is no 'append' methodmyClosure()
def buffer = new StringBuffer()def myClosure = { append('First Line\n') append('Last Line\n')}myClosure.delegate = buffer// will append to the StringBuffermyClosure()
Closure Delegates
class User {
String login String password String email Date age
static constraints = { login(length:5..15,blank:false,unique:true) password(length:5..15,blank:false) email(email:true,blank:false) age(min:new Date(),nullable:false) }}
MarkupBuilder
def mkp = new groovy.xml.MarkupBuilder()mkp.html { head { title('My MarkupBuilder Test') } body { h2('My Favorite Sites') ul { li('groovy.codehaus.org') li('grails.org') li('javajeff.blogspot.com') } }}
Remember that this is executable code. All of those tag names are method calls that are being intercepted by the builder.
MarkupBuilder
<html> <head> <title>My MarkupBuilder Test</title> </head> <body> <h2>My Favorite Sites</h2> <ul> <li>groovy.codehaus.org</li> <li>grails.org</li> <li>javajeff.blogspot.com</li> </ul> </body></html>
ExpandoMetaClass
String.metaClass.vowels = { delegate.findAll { it.toLowerCase().matches('[aeiou]') }}def message = 'Groovy Is A Great Language'println message.vowels()// ["o", "o", "I", "A", "e", "a", "a", "u", "a", "e"]
Thank You For Coming
Q & A