Groovy Metaprogramming
Metaprogramming in Groovy allows you to modify classes and objects at runtime, adding or changing behavior dynamically.
Runtime Metaprogramming
Add methods to classes or individual objects at runtime:
// Add method to String class
String.metaClass.shout = { -> delegate.toUpperCase() + "!" }
println "hello".shout() // "HELLO!"
// Add method to a specific instance
def person = new Person(name: 'Alice')
person.metaClass.greet = { "Hello, ${delegate.name}!" }
println person.greet() // "Hello, Alice!"
Expando Objects
Dynamic objects that can have properties and methods added at runtime:
def person = new Expando()
person.name = 'Alice'
person.greet = { "Hello, ${person.name}!" }
println person.greet() // "Hello, Alice!"
Method Missing
Handle calls to non-existent methods:
class DynamicPerson {
def methodMissing(String name, args) {
"Called $name with ${args.join(', ')}"
}
}
def p = new DynamicPerson()
println p.sayHello('Alice') // "Called sayHello with Alice"
Property Missing
Handle access to non-existent properties:
class DynamicConfig {
def propertyMissing(String name) {
"Property $name not found"
}
}
def config = new DynamicConfig()
println config.serverUrl // "Property serverUrl not found"
Compile-time Metaprogramming (AST Transformations)
Modify the AST (Abstract Syntax Tree) during compilation:
@ToString
@EqualsAndHashCode
@TupleConstructor
class Person {
String name
int age
}
// The annotations above generate toString(), equals(), hashCode()
// and constructors at compile time
Common AST Transformations
@Immutable
: Creates immutable class@Delegate
: Delegates methods to a field@Singleton
: Creates a singleton@Log
: Adds logger field@Builder
: Creates builder pattern
Creating Custom AST Transformations
You can create your own AST transformations for code generation:
@Retention(RetentionPolicy.SOURCE)
@Target([ElementType.TYPE])
@GroovyASTTransformationClass("com.example.TimestampASTTransformation")
public @interface Timestamp {}
← Back to Tutorials