Начиная с Groovy 2.3, мы можем легко создать свободный API для наших классов с помощью преобразования @Builder
AST. Мы можем применить аннотацию к нашим классам, и полученный файл классов будет иметь все необходимые методы для поддержки свободного API. Мы можем настроить способ создания свободного API с различными параметрами аннотации. В коде Groovy мы уже можем использовать метод with
чтобы иметь чистый способ установки значений свойств или использовать именованные аргументы конструктора. Но если наши классы нужно использовать из Java, было бы неплохо дать разработчикам Java свободный API для наших классов Groovy.
В следующем примере мы применяем аннотацию @Builder
к простому классу Message
с некоторыми свойствами. Мы оставляем все в настройках по умолчанию, и тогда полученный файл класса Message
будет иметь новый метод builder
который возвращает внутренний вспомогательный класс, который мы можем использовать для установки наших свойств. Для каждого свойства свой новый метод с именем свойства, поэтому мы можем установить значение. И, наконец, наш класс содержит build
которая будет возвращать новый экземпляр класса Message
с правильными значениями для свойств.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
import groovy.transform.builder.Builder @Builder class Message { String from, to, subject, body } def message = Message .builder() // New internal helper class. .subject( 'Sample mail' ) .body( 'Groovy rocks!' ) .build() // Create instance of Message assert message.body == 'Groovy rocks!' assert message.subject == 'Sample mail' |
Если мы хотим изменить имена builderMethodName
и методов build
мы можем использовать параметры аннотации builderMethodName
и buildMethodName
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
import groovy.transform.builder.Builder @Builder (builderMethodName = 'initiator' , buildMethodName = 'create' ) class Message { String from, to, subject, body } def message = Message.initiator() .body( 'Groovy rocks!' ) .create() assert message.body == 'Groovy rocks!' |
Мы видим, что для каждого свойства генерируется соответствующий метод. Мы также можем настроить префикс для сгенерированного имени метода с prefix
параметра аннотации. В следующем примере мы определяем префикс, назначаемый для имен методов:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
import groovy.transform.builder.Builder @Builder (prefix = 'assign' ) class Message { String from, to, subject, body } def message = Message.builder() .assignBody( 'Groovy rocks!' ) .build() assert message.body == 'Groovy rocks!' |
Наконец, мы также можем включать и исключать свойства, которые необходимо включить или исключить из нашего свободного API. Мы используем параметры аннотации include и excludes
для определения имен свойств. Это может быть список или список имен через запятую.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
import groovy.transform.builder.Builder @Builder (excludes = 'body' /* or includes = 'from,to,subject' */ ) class Message { String from, to, subject, body } def message = Message.builder() .subject( 'Groovy 2.3 is released' ) .build() assert message.subject == 'Groovy 2.3 is released' try { message = Message.builder().body( 'Groovy rocks!' ).build() } catch (MissingMethodException e) { assert e.message.readLines().first() == 'No signature of method: static Message.body() is applicable for argument types: (java.lang.String) values: [Groovy rocks!]' } |
Преобразование @Builder
AST также проверяет, применяется @Canonical
преобразование @Canonical
AST к классу. Любые включенные или исключенные свойства, определенные в преобразовании @Canonical
, также включаются или исключаются для сгенерированного кода компоновщика.
Мы можем определить стратегию SimpleStrategy
с помощью параметра аннотации builderStrategy
. Тогда сгенерированный класс не будет иметь отдельного внутреннего класса помощника и метода сборки. prefix
умолчанию установлен на set
, но мы можем изменить его, если захотим:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
import groovy.transform.builder.Builder import groovy.transform.builder.SimpleStrategy @Builder (builderStrategy = SimpleStrategy, prefix = 'assign' ) class Message { String from, to, subject, body } def message = new Message() .assignSubject( 'Sample mail' ) .assignBody( 'Groovy rocks!' ) assert message.body == 'Groovy rocks!' assert message.subject == 'Sample mail' |
Мы увидим другую особенность аннотации @Builder
в будущих сообщениях в блоге.
Код написанный с Groovy 2.3.
Ссылка: | Groovy Goodness: используйте Builder AST Transformation для Fluent API от нашего партнера по JCG Хьюберта Иккинка в блоге JDriven . |