「XYZClientWrapper」というクラスがあり、次の構造があります。
@Builder
XYZClientWrapper{
String name;
String domain;
XYZClient client;
}
プロパティXYZClient client
に対してビルド関数を生成しないこと
Lombokはそのようなユースケースをサポートしていますか?
はい。必要なフィールドのみを含むコンストラクタまたは静的(ファクトリ)メソッドに @ Builder を配置できます。
開示:私はロンボク島の開発者です。
あるいは、フィールドをfinal、staticまたはstatic finalとしてマークすると、@Builder
このフィールドを無視します。
@Builder
public class MyClass {
private String myField;
private final String excludeThisField = "bar";
}
ロンボク1.16.1
静的なBuilderクラスの「シェル」を実装し、非表示にするメソッドをプライベートアクセス修飾子で追加でき、ビルダーではアクセスできなくなっていることがわかりました。同様に、ビルダーにカスタムメソッドを追加することもできます。
package com.something;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import Java.time.ZonedDateTime;
@Data
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MyClass{
//The builder will generate a method for this property for us.
private String anotherProperty;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "localDateTime", column = @Column(name = "some_date_local_date_time")),
@AttributeOverride(name = "zoneId", column = @Column(name = "some__date_zone_id"))
})
@Getter(AccessLevel.PRIVATE)
@Setter(AccessLevel.PRIVATE)
private ZonedDateTimeEmbeddable someDateInternal;
public ZonedDateTime getSomeDate() {
return someDateInternal.toZonedDateTime();
}
public void setSomeDate(ZonedDateTime someDate) {
someDateInternal = new ZonedDateTimeEmbeddable(someDate);
}
public static class MyClassBuilder {
//Prevent direct access to the internal private field by pre-creating builder method with private access.
private MyClassBuilder shipmentDateInternal(ZonedDateTimeEmbeddable zonedDateTimeEmbeddable) {
return this;
}
//Add a builder method because we don't have a field for this Type
public MyClassBuilder someDate(ZonedDateTime someDate) {
someDateInternal = new ZonedDateTimeEmbeddable(someDate);
return this;
}
}
}
コードでビルダーを作成し、プロパティのプライベートセッターを追加します。
@Builder
XYZClientWrapper{
String name;
String domain;
XYZClient client;
public static class XYZClientWrapperBuilder {
private XYZClientWrapperBuilder client(XYZClient client) { return this; }
}
}
これが私の好ましい解決策です。これにより、フィールドclient
を最後に作成し、ビルダーによって以前に設定された他のフィールドに依存させることができます。
XYZClientWrapper{
String name;
String domain;
XYZClient client;
@Builder
public XYZClientWrapper(String name, String domain) {
this.name=name;this.domain=domain;
this.client=calculateClient();
}
}
工場出荷時の静的メソッドの例
Class Car{
private String name;
private String model;
private Engine engine; // we want to ignore setting this
@Builder
public static Car of(String name, String model){
Car car=new Car();
car.setName(name);
car.setModel(model);
constructEngine(); // some private method to construct engine internally
return car;
}
private constructEngine(){// construct engine internally}
}
次のように使用できます:
main(String[] args){
Car toyotaCorollaCar=Car.builder().name("Toyota").model("Corolla");
// You can see now that Car.builder().engine() is not available
}
Build()が呼び出されるたびに静的メソッドof
が呼び出されることに注意してください。そのため、Car.builder().name("Toyota")
のようなものを実行しても、build()
が呼び出されてからコンストラクターの静的メソッドname
が割り当てられない限り、実際に"Toyota"
をof
に設定しません。
もう1つの解決策が見つかりました。フィールドを開始済み最終ラッパーまたはプロキシにラップできます。 AtomicReferenceにラップする最も簡単な方法。
@Builder
public class Example {
private String field1;
private String field2;
private final AtomicReference<String> excluded = new AtomicReference<>(null);
}
Getメソッドとsetメソッドを使用して内部で操作できますが、ビルダーには表示されません。
excluded.set("Some value");
excluded.get();