Groovy @Bindable and @Vetoable annotations

Рубрика: Groovy | 2 July 2008, 22:48 | Vadim Voituk

Начиная с первых “бэт” версии 1.6 в Groovy были добавлены 2 встроенные аннотации (да-да! Groovy наконец-то полностью поддержирживает все возможности Java5!) : groovy.beans.Bindable и groovy.beans.Vetoable

Обе аннотации содержат в себе функионал который призван заменить стандартные Java-интерфейсы java.beans.PropertyChangeListener и java.beans.VetoableChangeListener и избавить разработчика от обилия классов-слушателей (listeners) и декларации дополнительных интерфейсов для бина.

Об этих нововведениях и их назначении было напечатано/перепечатано в каждом обзоре новых “фич” версии 1.6, но при этом нигде не встречалось описания как же все-таки “повесить” свой обработчик событий (listener).

Немного поковырявшись в исходниках Groovy удалось узнать такое:

1. При использовании аннотации @Bindable, сообщение об изменении значния свойства обьекта передается в замыкание, указанное в специальном свойстве propertyChange (имя совпадает с именем метода в PropertyChangeListener), в пределах того же бина, в котором произошло изменение.
При этом аргументом замыкания является экземпляр класса java.beans.PropertyChangeEvent.

2. Аналогично при использовании аннотации Vetoable используется замыкание, определенное в свойстве vetoableChange с тем же типом параметра замыкания (PropertyChangeEvent).

Пример использования аннотация @Bindable

import groovy.beans.Bindable

class MyClass {
  @Bindable int id
  @Bindable String name
  def MyClass() {
    //this.propertyChange = {
    //   println it.propertyName + " changed from " + it.oldValue + " to " + it.newValue
    //}
  }
}

def x = new MyClass()
x.propertyChange = {
    println it.propertyName + " changed from " + it.oldValue + " to " + it.newValue
}
x.id = 10
x.name = "Hello"

Результат будет выглядеть так:
groovy Test.groovy
id changed from 0 to 10
name changed from null to Hello

Причем инициализацию свойства propertyChange можно проводить и в конструкторе (см. закомментированный код), но при этом нельзя восплользоваться статической инициализацией (почему? Не знаю).

Тоесть такой пример работать не будет:

class MyClass {
  def propertyChange = {println it}
  @Bindable int id
}
def x = new MyClass()
x.id = 10

Оставьте комментарий!

Leave a Reply