Go...

当前位置: 首页>>世界杯太太团

Groovy 语言文档

@groovy.transform.builder.Builder

@Builder AST 转换用于帮助编写可以使用*流式* API 调用创建的类。该转换支持多种构建策略以涵盖各种情况,并且有许多配置选项可以自定义构建过程。如果您是 AST 黑客,您还可以定义自己的策略类。下表列出了 Groovy 中捆绑的可用策略以及每种策略支持的配置选项。

策略

描述

builderClassName

builderMethodName

buildMethodName

prefix

includes/excludes

includeSuperProperties

allNames

SimpleStrategy

链式setter

不适用

不适用

不适用

是,默认“set”

是

不适用

是,默认 false

ExternalStrategy

显式构建器类,正在构建的类不受影响

不适用

不适用

是,默认“build”

是,默认“”

是

是,默认 false

是,默认 false

DefaultStrategy

创建一个嵌套辅助类

是,默认 Builder

是,默认“builder”

是,默认“build”

是,默认“”

是

是,默认 false

是,默认 false

InitializerStrategy

创建一个提供类型安全流畅创建的嵌套辅助类

是,默认 Initializer

是,默认“createInitializer”

是,默认“create”,但通常仅在内部使用

是,默认“”

是

是,默认 false

是,默认 false

SimpleStrategy

要使用 SimpleStrategy,请使用 @Builder 注解您的 Groovy 类,并指定策略,如本例所示:

import groovy.transform.builder.*

@Builder(builderStrategy=SimpleStrategy)

class Person {

String first

String last

Integer born

}

然后,只需像这样以链式方式调用 setter:

def p1 = new Person().setFirst('Johnny').setLast('Depp').setBorn(1963)

assert "$p1.first $p1.last" == 'Johnny Depp'

对于每个属性,将创建一个生成的 setter,如下所示:

public Person setFirst(java.lang.String first) {

this.first = first

return this

}

您可以指定一个前缀,如本例所示:

import groovy.transform.builder.*

@Builder(builderStrategy=SimpleStrategy, prefix="")

class Person {

String first

String last

Integer born

}

调用链式 setter 将如下所示:

def p = new Person().first('Johnny').last('Depp').born(1963)

assert "$p.first $p.last" == 'Johnny Depp'

您可以将 SimpleStrategy 与 @TupleConstructor 结合使用。如果您的 @Builder 注解没有显式的 includes 或 excludes 注解属性,但您的 @TupleConstructor 注解有,那么 @TupleConstructor 中的属性将被 @Builder 重用。这同样适用于任何组合 @TupleConstructor 的注解别名,例如 @Canonical。

如果您希望在构造过程中调用某个 setter,可以使用 useSetters 注解属性。详情请参阅 JavaDoc。

此策略不支持注解属性 builderClassName、buildMethodName、builderMethodName、forClass 和 includeSuperProperties。

Groovy 已经内置了构建机制。如果内置机制满足您的需求,请不要急于使用 @Builder。以下是一些示例:

def p2 = new Person(first: 'Keira', last: 'Knightley', born: 1985)

def p3 = new Person().with {

first = 'Geoffrey'

last = 'Rush'

born = 1951

}

ExternalStrategy

要使用 ExternalStrategy,请使用 @Builder 注解创建和注解 Groovy 构建器类,使用 forClass 指定构建器适用的类,并指示使用 ExternalStrategy。假设您有以下想要为其构建器的类:

class Person {

String first

String last

int born

}

您显式创建并使用构建器类,如下所示:

import groovy.transform.builder.*

@Builder(builderStrategy=ExternalStrategy, forClass=Person)

class PersonBuilder { }

def p = new PersonBuilder().first('Johnny').last('Depp').born(1963).build()

assert "$p.first $p.last" == 'Johnny Depp'

请注意,您提供的(通常为空的)构建器类将填充适当的 setter 和构建方法。生成的构建方法将类似于:

public Person build() {

Person _thePerson = new Person()

_thePerson.first = first

_thePerson.last = last

_thePerson.born = born

return _thePerson

}

您正在为其创建构建器的类可以是遵循正常 JavaBean 约定的任何 Java 或 Groovy 类,例如,无参数构造函数和属性的 setter。这是一个使用 Java 类的示例:

import groovy.transform.builder.*

@Builder(builderStrategy=ExternalStrategy, forClass=javax.swing.DefaultButtonModel)

class ButtonModelBuilder {}

def model = new ButtonModelBuilder().enabled(true).pressed(true).armed(true).rollover(true).selected(true).build()

assert model.isArmed()

assert model.isPressed()

assert model.isEnabled()

assert model.isSelected()

assert model.isRollover()

生成的构建器可以使用 prefix、includes、excludes 和 buildMethodName 注解属性进行自定义。这是一个说明各种自定义的示例:

import groovy.transform.builder.*

import groovy.transform.Canonical

@Canonical

class Person {

String first

String last

int born

}

@Builder(builderStrategy=ExternalStrategy, forClass=Person, includes=['first', 'last'], buildMethodName='create', prefix='with')

class PersonBuilder { }

def p = new PersonBuilder().withFirst('Johnny').withLast('Depp').create()

assert "$p.first $p.last" == 'Johnny Depp'

此策略不适用于 @Builder 的 builderMethodName 和 builderClassName 注解属性。

您可以将 ExternalStrategy 与 @TupleConstructor 结合使用。如果您的 @Builder 注解没有显式的 includes 或 excludes 注解属性,但您正在为其创建构建器的类的 @TupleConstructor 注解有,那么 @TupleConstructor 中的属性将被 @Builder 重用。这同样适用于任何组合 @TupleConstructor 的注解别名,例如 @Canonical。

DefaultStrategy

要使用 DefaultStrategy,请使用 @Builder 注解您的 Groovy 类,如本例所示:

import groovy.transform.builder.Builder

@Builder

class Person {

String firstName

String lastName

int age

}

def person = Person.builder().firstName("Robert").lastName("Lewandowski").age(21).build()

assert person.firstName == "Robert"

assert person.lastName == "Lewandowski"

assert person.age == 21

如果您愿意,可以使用 builderClassName、buildMethodName、builderMethodName、prefix、includes 和 excludes 注解属性自定义构建过程的各个方面,其中一些在本例中有所使用:

import groovy.transform.builder.Builder

@Builder(buildMethodName='make', builderMethodName='maker', prefix='with', excludes='age')

class Person {

String firstName

String lastName

int age

}

def p = Person.maker().withFirstName("Robert").withLastName("Lewandowski").make()

assert "$p.firstName $p.lastName" == "Robert Lewandowski"

此策略还支持注释静态方法和构造函数。在这种情况下,静态方法或构造函数参数将成为用于构建目的的属性,在静态方法的情况下,方法的返回类型将成为正在构建的目标类。如果一个类中使用了多个 @Builder 注解(在类、方法或构造函数位置),则由您来确保生成的辅助类和工厂方法具有唯一的名称(即不能有多个使用默认名称值)。有关方法和构造函数使用示例,但使用 DefaultStrategy 策略,请参阅该策略的文档。

import groovy.transform.builder.*

import groovy.transform.*

@ToString

@Builder

class Person {

String first, last

int born

Person(){}

@Builder(builderClassName='MovieBuilder', builderMethodName='byRoleBuilder')

Person(String roleName) {

if (roleName == 'Jack Sparrow') {

this.first = 'Johnny'; this.last = 'Depp'; this.born = 1963

}

}

@Builder(builderClassName='NameBuilder', builderMethodName='nameBuilder', prefix='having', buildMethodName='fullName')

static String join(String first, String last) {

first + ' ' + last

}

@Builder(builderClassName='SplitBuilder', builderMethodName='splitBuilder')

static Person split(String name, int year) {

def parts = name.split(' ')

new Person(first: parts[0], last: parts[1], born: year)

}

}

assert Person.splitBuilder().name("Johnny Depp").year(1963).build().toString() == 'Person(Johnny, Depp, 1963)'

assert Person.byRoleBuilder().roleName("Jack Sparrow").build().toString() == 'Person(Johnny, Depp, 1963)'

assert Person.nameBuilder().havingFirst('Johnny').havingLast('Depp').fullName() == 'Johnny Depp'

assert Person.builder().first("Johnny").last('Depp').born(1963).build().toString() == 'Person(Johnny, Depp, 1963)'

此策略不支持 forClass 注解属性。

InitializerStrategy

要使用 InitializerStrategy,请使用 @Builder 注解您的 Groovy 类,并指定策略,如本例所示:

import groovy.transform.builder.*

import groovy.transform.*

@ToString

@Builder(builderStrategy=InitializerStrategy)

class Person {

String firstName

String lastName

int age

}

您的类将被锁定为只有一个公共构造函数,该构造函数接受一个“完全设置”的初始化器。它还将有一个工厂方法来创建初始化器。它们的使用方式如下:

@CompileStatic

def firstLastAge() {

assert new Person(Person.createInitializer().firstName("John").lastName("Smith").age(21)).toString() == 'Person(John, Smith, 21)'

}

firstLastAge()

任何涉及设置所有属性(尽管顺序不重要)的初始化器使用尝试都将导致编译错误。如果您不需要这种严格性级别,则无需使用 @CompileStatic。

您可以将 InitializerStrategy 与 @Canonical 和 @Immutable 结合使用。如果您的 @Builder 注解没有显式的 includes 或 excludes 注解属性,但您的 @Canonical 注解有,则 @Canonical 中的属性将重新用于 @Builder。这里有一个使用 @Builder 与 @Immutable 的示例:

import groovy.transform.builder.*

import groovy.transform.*

import static groovy.transform.options.Visibility.PRIVATE

@Builder(builderStrategy=InitializerStrategy)

@Immutable

@VisibilityOptions(PRIVATE)

class Person {

String first

String last

int born

}

def publicCons = Person.constructors

assert publicCons.size() == 1

@CompileStatic

def createFirstLastBorn() {

def p = new Person(Person.createInitializer().first('Johnny').last('Depp').born(1963))

assert "$p.first $p.last $p.born" == 'Johnny Depp 1963'

}

createFirstLastBorn()

如果您希望在构造过程中调用某个 setter,可以使用 useSetters 注解属性。详情请参阅 JavaDoc。

此策略还支持注释静态方法和构造函数。在这种情况下,静态方法或构造函数参数将成为用于构建目的的属性,在静态方法的情况下,方法的返回类型将成为正在构建的目标类。如果一个类中使用了多个 @Builder 注解(在类、方法或构造函数位置),则由您来确保生成的辅助类和工厂方法具有唯一的名称(即不能有多个使用默认名称值)。有关方法和构造函数使用示例,但使用 DefaultStrategy 策略,请参阅该策略的文档。

此策略不支持 forClass 注解属性。