Metaprogramming With The Groovy Runtime - Part 1 of 2

Post on 18-Nov-2014

236 views 2 download

description

Speaker: Jeff Scott Brown The dynamic runtime nature of Groovy is one of the things that sets it apart from standard Java and makes it a fantastic language for building dynamic applications for the Java Platform. The metaprogramming capabilities offered by the language provide everything that an application development team needs to build systems that are far more capable than their all Java counterparts. This Part 1 of 2 will cover the runtime metaprogramming capabilities of Groovy. The session will dive deep into Groovy's Meta Object Protocol (MOP) which implements the incredibly dynamic runtime dispatch mechanism. The session will include a lot of live code demonstrating really powerful runtime features of the language. This session is focused specifically on Groovy's runtime metaprogramming capabilities. Part 2 of 2 will cover Groovy's compile time metaprogramming capabilities.

transcript

© 2013 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Metaprogramming With The Groovy Runtime – Part 1 of 2

Jeff Scott Brown@jeffscottbrown

jbrown@gopivotal.com

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