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 注解属性。