runtime metaprogramming with groovy

Post on 12-Apr-2017

240 Views

Category:

Technology

5 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Runtime Metaprogramming

With GroovyJeff Scott Brown @jeffscottbrown

brownj@ociweb.com

More at ociweb.com/grails

Copyright (c) 2015 Object Computing, Inc. All rights reserved.

WE ARE HIRING!

Groovy And Grails Project Work Grails 2 -> 3 Plugin Migrations Grails Plugin Development Expanding GORM’s Reach New Application Profiles Grails Core Development

grailsjobs@ociweb.com

Copyright (c) 2015 Object Computing, Inc. All rights reserved.

● What Is It? − behavior changes at runtime − capabilities are introduced at runtime − Wikipedia says...

Metaprogramming

“Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves)...”

Copyright (c) 2015 Object Computing, Inc. All rights reserved.

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

Copyright (c) 2015 Object Computing, Inc. All rights reserved.

Expando● Dynamically Expanding Object

def 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

Copyright (c) 2015 Object Computing, Inc. All rights reserved.

Runtime Mappingsexpando.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[])

Copyright (c) 2015 Object Computing, Inc. All rights reserved.

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...

Copyright (c) 2015 Object Computing, Inc. All rights reserved.

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

Copyright (c) 2015 Object Computing, Inc. All rights reserved.

Closure Delegatesdef myClosure = { append('First Line\n') append('Last Line\n') } // will fail because there is no 'append' method myClosure()

def buffer = new StringBuffer() def myClosure = { append('First Line\n') append('Last Line\n') } myClosure.delegate = buffer // will append to the StringBuffer myClosure()

Copyright (c) 2015 Object Computing, Inc. All rights reserved.

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

Copyright (c) 2015 Object Computing, Inc. All rights reserved.

MarkupBuilderdef 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.

Copyright (c) 2015 Object Computing, Inc. All rights reserved.

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>

Copyright (c) 2015 Object Computing, Inc. All rights reserved.

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"]

Q&A

Jeff Scott Brown @jeffscottbrown

brownj@ociweb.com

top related