Groovy 使用Builder AST 轉換為流式API
- 2019 年 10 月 4 日
- 筆記
從Groovy 2.3開始,我們可以使用@Builder
AST轉換輕鬆地為我們的類創建一個流暢的API。 我們可以將注釋應用於我們的類,結果類文件將具有支援流暢API的所有必要方法。 我們可以自定義如何使用不同的注釋參數生成流暢的API。 在Groovy程式碼中,我們已經可以使用with
方法 有一個簡潔的方法來設置屬性值或使用 命名的構造函數參數。 但是如果我們的類需要從Java中使用,那麼為Java開發人員提供一個流暢的API來為我們的Groovy類做很好。
在下面的示例中,我們將@Builder
注釋應用於具有一些屬性的簡單類Message
。 我們將所有內容保留為默認設置,然後生成的Message
類文件將有一個新的builder
方法,該方法返回一個內部幫助器類,我們可以使用它來設置我們的屬性。 對於每個屬性,它們是一個帶有屬性名稱的新方法,因此我們可以設置一個值。 最後,我們的類包含一個build
,它將返回一個具有正確屬性值的Message
類的新實例。
import groovy.transform.builder.Builder @Builder class Message { String from, to, subject, body } def message = Message .builder() // New internal helper class. .from('[email protected]') // Method per property. .to('[email protected]') .subject('Sample mail') .body('Groovy rocks!') .build() // Create instance of Message assert message.body == 'Groovy rocks!' assert message.from == '[email protected]' assert message.subject == 'Sample mail' assert message.to == '[email protected]' //If we want to change the names of the builder and build methods we can //use the annotation parameters builderMethodName andbuildMethodName: import groovy.transform.builder.Builder @Builder(builderMethodName = 'initiator', buildMethodName = 'create') class Message { String from, to, subject, body } def message = Message.initiator() .from('[email protected]') .body('Groovy rocks!') .create() assert message.body == 'Groovy rocks!' assert message.from == '[email protected]' //We see that for each property a corresponding method is generated. We //can also customize the prefix for the generated method name with the //annotation parameter prefix. In the following sample we define the //prefix assign for the method names: import groovy.transform.builder.Builder @Builder(prefix = 'assign') class Message { String from, to, subject, body } def message = Message.builder() .assignFrom('[email protected]') .assignBody('Groovy rocks!') .build() assert message.body == 'Groovy rocks!' assert message.from == '[email protected]' //Finally we can also include and exclude properties to need to be //included or excluded from our fluent API. We use the annotation //parametersincludes and excludes to define the names of the properties. //This can be a list or a comma separated list of names. import groovy.transform.builder.Builder @Builder(excludes = 'body' /* or includes = 'from,to,subject' */) class Message { String from, to, subject, body } def message = Message.builder() .from('[email protected]') .to('[email protected]') .subject('Groovy 2.3 is released') .build() assert message.from == '[email protected]' 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
AST轉換是否應用於類。 對於生成的構建器程式碼,還包括或排除在@Canonical
轉換中定義的任何包含或排除的屬性。
我們可以使用builderStrategy
注釋參數定義SimpleStrategy
策略。 然後生成的類將沒有單獨的內部幫助器構建器類和構建方法。 默認的prefix
設置為set
,但如果我們想要,我們可以更改:
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() .assignFrom('[email protected]') // Method per property. .assignTo('[email protected]') .assignSubject('Sample mail') .assignBody('Groovy rocks!') assert message.body == 'Groovy rocks!' assert message.from == '[email protected]' assert message.subject == 'Sample mail' assert message.to == '[email protected]'
我們將在未來的部落格文章中看到@ Builder
注釋的其他功能。