Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Andrey Adamovich - Groovy 2 Cookbook - 2013.pdf
Скачиваний:
44
Добавлен:
19.03.2016
Размер:
26.28 Mб
Скачать

9

Metaprogramming and DSLs in Groovy

In this chapter, we will cover:

ff

ff

ff

ff

ff

ff

ff

ff

Querying methods and properties

Dynamically extending classes with new methods Overriding methods dynamically

Adding performance logging to methods Adding a caching functionality around methods Adding transparent imports to a script

DSL for executing commands over SSH

DSL for generating reports from logfiles

Introduction

The recipes presented in this chapter will cover a number of advanced metaprogramming concepts in Groovy in detail. Metaprogramming is the characteristic of a programming language to modify the aspect of a class at runtime or compile time, that is, adding and intercepting methods, implementing new interfaces, and so on.

Groovy, thanks to its dynamic nature, makes metaprogramming extremely easy. This capability is considered by many to be one of the most helpful features of the language.

www.it-ebooks.info

Metaprogramming and DSLs in Groovy

Taking an advantage of Groovy's metaprogramming capabilities bring great new possibilities that would be very difficult or just plain impossible to write with Java alone. The first recipes of this chapter cover several interesting solutions such as dynamically adding methods to classes, intercepting methods, and exploring Abstract Syntax Tree (AST) capabilities.

Metaprogramming is especially important for the creation of DSLs (Domain Specific

Language), small domain-specific languages dedicated to a particular domain problem.

In this chapter, we will also dedicate two recipes to different aspects of how to write a DSL with Groovy.

Querying methods and properties

In this first recipe about metaprogramming, we begin by looking at the introspection capabilities of Groovy. Introspection is a major feature of the Java language and, by extension, of the Groovy language. Using introspection, we can get the internal information of a class at runtime, including fields, methods, constructors, and so on.

Getting ready

To test out the introspection feature, let's create a couple of Groovy classes:

package org.groovy.cookbook

class Book {

String title

Author author

Long year

Long pages

Long getAmazonSalesPosition() { new Random().nextInt(1) + 1

}

void attachReview(String review) { }

}

class Author { String name String lastName

}

290

www.it-ebooks.info

Chapter 9

How to do it...

The following steps offer an example of the introspection capabilities of the language:

1.To check the type of a class, you can just execute the following code snippet:

assert 'java.lang.String' == String.name

assert 'org.groovy.cookbook.Author' == Author.name

2.To list all the properties of the object:

Author a = new Author(name: 'Ernest', lastName: 'Hemingway')

Book book = new Book() book.with {

title = 'The Old Man and the Sea' year = 1952

pages = 200 author = a

}

book.properties.each { println it }

The output of looping on the instance's properties is as follows:

title=The Old Man and the Sea class=class org.groovy.cookbook.Book amazonSalesPosition=1

year=1952

pages=200

metaClass=

org.codehaus.groovy.runtime.HandleMetaClass

@41ce774e[groovy.lang.MetaClassImpl@41ce774e[ class org.groovy.cookbook.Book]]

author=org.groovy.cookbook.Author@59fac3a2

3.One of the properties returned from the query is metaClass. Through this property, we can access quite many interesting methods to figure out what our class can

do. For instance, to check the existence of a property, we can use the following code snippet:

assert book.metaClass.hasProperty(book, 'pages')

291

www.it-ebooks.info

Metaprogramming and DSLs in Groovy

4.Or list all the methods and properties:

println '#### METHODS ####'

book.metaClass.methods.each { println it }

println '#### PROPERTIES ####'

book.metaClass.properties.each { println it.name }

Note how the methods' property prints all the methods inherited from Java (such as equals and hashCode) as well as the local methods of the class:

### METHODS ####

public boolean java.lang.Object.equals(java.lang.Object)

public final native java.lang.Class java.lang.Object.getClass() public native int java.lang.Object.hashCode()

...

public void Book.attachReview(java.lang.String) public java.lang.Long Book.getAmazonSalesPosition() public Author Book.getAuthor()

public groovy.lang.MetaClass Book.getMetaClass() public java.lang.Long Book.getPages()

...

### PROPERTIES ###

title class

amazonSalesPosition year

pages author

5.Finally, the metaClass gives access to the respondsTo method, to directly interrogate an instance about the presence of a method:

assert book.metaClass.respondsTo(book,'getAmazonSalesPosition') assert book.metaClass.respondsTo(book,'attachReview', String)

The respondsTo method can be directly invoked on any object, as it is also exposed on the Groovy enhanced java.lang.Object class:

assert book.respondsTo('attachReview', String)

292

www.it-ebooks.info

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]