롬복 빌더에서 부동산을 제외하려면 어떻게 해야 합니까?
'XYZClientWrapper'라는 클래스가 있습니다.이 클래스는 다음과 같습니다.
@Builder
XYZClientWrapper{
String name;
String domain;
XYZClient client;
}
속성에 대해 빌드 함수를 생성하지 않을 내용XYZClient client
Lombok은 이러한 사용 사례를 지원합니까?
네, @Builder를 컨스트럭터 또는 정적(공장 출하시) 메서드에 배치할 수 있습니다.이 메서드는 원하는 필드만 포함합니다.
공개:저는 롬복 개발자입니다.
또는 최종, 정적 또는 정적 최종 명령으로 필드를 표시하는 것을 발견했습니다.@Builder
이 필드를 무시합니다.
@Builder
public class MyClass {
private String myField;
private final String excludeThisField = "bar";
}
롬복 1.16.10
코드로 작성기를 만들고 속성에 대한 개인 설정기를 추가합니다.
@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
private static Car of(String name, String model){
Car car=new Car();
car.name = name;
car.model = model;
constructEngine(car); // some static private method to construct engine internally
return car;
}
private static void constructEngine(Car car) {
// car.engine = blabla...
// construct engine internally
}
}
다음과 같이 사용할 수 있습니다.
Car toyotaCorollaCar=Car.builder().name("Toyota").model("Corolla").build();
// You can see now that Car.builder().engine() is not available
스태틱 방식에 주의해 주십시오.of
build()가 호출될 때마다 호출되므로 다음과 같은 작업을 수행합니다.Car.builder().name("Toyota")
실제로 값을 설정하지는 않습니다."Toyota"
안으로name
~하지 않는 한build()
호출된 후 생성자 정적 메서드 내에서 로직을 할당합니다.of
실행됩니다.
또, 다음의 점에 주의해 주세요.of
방법은 비공개로 접근하기 때문에build
method는 발신자가 볼 수 있는 유일한 방식입니다.
정적 Builder 클래스의 "쉘"을 구현하고 개인 액세스 수식자로 숨길 메서드를 추가할 수 있으며, 더 이상 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;
}
}
}
해결 방법을 하나 더 찾았습니다. 필드를 시작된 최종 래퍼 또는 프록시로 래핑할 수 있습니다.Atomic Reference로 정리하는 가장 쉬운 방법입니다.
@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();
Lombok을 사용한 클래스에 이른바 '부분 빌더' 추가@Builder
도움이 됩니다.요령은 다음과 같이 내부 부분 빌더 클래스를 추가하는 것입니다.
@Getter
@Builder
class Human {
private final String name;
private final String surname;
private final Gender gender;
private final String prefix; // Should be hidden, depends on gender
// Partial builder to manage dependent fields, and hidden fields
public static class HumanBuilder {
public HumanBuilder gender(final Gender gender) {
this.gender = gender;
if (Gender.MALE == gender) {
this.prefix = "Mr.";
} else if (Gender.FEMALE == gender) {
this.prefix = "Ms.";
} else {
this.prefix = "";
}
return this;
}
// This method hides the field from external set
private HumanBuilder prefix(final String prefix) {
return this;
}
}
}
PS: @Builder에서는 생성된 빌더 클래스 이름을 변경할 수 있습니다.위의 예에서는 기본 빌더 클래스 이름이 사용되는 것으로 가정하고 있습니다.
다른 접근법이 있습니다.@Delegate
그리고.Inner Class
는 제외된 필드에 대해 "값 표시"를 지원합니다.
먼저 제외할 필드를 이동한다.Inner Class
롬복에게 빌더에 그들을 포함시키지 않기 위해서죠
'우리'를 사용합니다.@Delegate
겟터/셋터
예:
@Builder
@Getter @Setter @ToString
class Person {
private String name;
private int value;
/* ... More builder-included fields here */
@Getter @Setter @ToString
private class BuilderIgnored {
private String position; // Not included in the Builder, and remain `null` until p.setPosition(...)
private String nickname; // Lazy initialized as `name+value`, but we can use setter to set a new value
/* ... More ignored fields here! ... */
public String getNickname(){ // Computed value for `nickname`
if(nickname == null){
nickname = name+value;
}
return nickname;
}
/* ... More computed fields' getters here! ... */
}
@Delegate @Getter(AccessLevel.NONE) // Delegate Lombok Getters/Setters and custom Getters
private final BuilderIgnored ignored = new BuilderIgnored();
}
합니다.Person
라고 분류하다position
★★★★★★★★★★★★★★★★★」nickname
실제로 내부 계층의 분야입니다.
Person p = Person.builder().name("Test").value(123).build();
System.out.println(p); // Person(name=Test, value=123, ignored=Person.BuilderIgnored(position=null, nickname=Test123))
p.setNickname("Hello World");
p.setPosition("Manager");
System.out.println(p); // Person(name=Test, value=123, ignored=Person.BuilderIgnored(position=Manager, nickname=Hello World))
장점:
- 는 강제로 하지 .
final
- 제외된 필드에 대해 계산된 값 지원
- 계산 필드가 빌더에 의해 설정된 필드를 참조하도록 허용(즉, 내부 클래스가 비정적 클래스가 되도록 허용
- 모든 필드 목록을 반복할 필요가 없습니다(예: 생성자에서 제외된 필드를 제외한 모든 필드 나열).
- Lombok을 .
@Builder
(:: 성))MyBuilder extends FooBuilder
)
단점:
- '아주 좋다'의입니다.
Inner Class
;, 을 합니다.private
수 Getters - 따라서 이 접근법에서는 Getters/Setters를 사용하여 제외된 필드에 액세스할 수 없습니다.
- 은 ""가 "Getters"가호출되었을 때 됩니다.
.build()
.
제가 좋아하고 사용하는 방법 중 하나는 이것입니다.필수 매개 변수를 생성자에 유지하고 작성기를 통해 선택 사항을 설정합니다.필요한 수가 많지 않을 때 작동합니다.
class A {
private int required1;
private int required2;
private int optional1;
private int optional2;
public A(int required1, int required2) {
this.required1 = required1;
this.required2 = required2;
}
@Builder(toBuilder = true)
public A setOptionals(int optional1, int optional2) {
this.optional1 = optional1;
this.optional2 = optional2;
return this;
}
}
그리고 나서 그것을 건설합니다.
A a = new A(1, 2).builder().optional1(3).optional2(4).build();
이 접근방식의 장점은 옵션에도 기본값을 설정할 수 있다는 것입니다.
이전에 사용한 접근법 중 하나는 인스턴스 필드를 Configuration 필드와 Session 필드로 그룹화하는 것입니다.컨피규레이션필드는 클래스인스턴스로서 Builder에 표시되며 Session 필드는 네스트됩니다. private static class
를 통해 할 수 .final
인스턴스 (빌더)
다음과 같은 경우:
@Builder
class XYZClientWrapper{
private String name;
private String domain;
private static class Session {
XYZClient client;
}
private final Session session = new Session();
private void initSession() {
session.client = ...;
}
public void foo() {
System.out.println("name: " + name);
System.out.println("domain: " + domain;
System.out.println("client: " + session.client);
}
}
하려면 , 「」를 사용해 .@Builder.Default
언급URL : https://stackoverflow.com/questions/30717640/how-to-exclude-property-from-lombok-builder
'programing' 카테고리의 다른 글
최소/최대와 주문 기준 및 제한 (0) | 2023.02.02 |
---|---|
Array List - 인덱스가 존재하는지 확인하려면 어떻게 해야 합니까? (0) | 2023.02.02 |
FIND_IN_SET() vs IN() (0) | 2023.02.02 |
vue 앱에서 처음 로드한 후 다이내믹 PixiJ 캔버스가 잘못됨 (0) | 2023.02.02 |
PHP 7에서 MySQLi 확장을 활성화하려면 어떻게 해야 합니까? (0) | 2023.02.02 |