web-dev-qa-db-ja.com

Lombokのビルダーでカスタムセッターを使用する

LombokベースのPOJOにカスタムセッターがあります。

@Data
@Builder
public class User {
    private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();

    private String password = null;

    public void setPassword(String password) {
        Assert.notNull(password);
        this.password = ENCODER.encode(password);
    }

しかし、Lombokで生成されたビルダーを使用すると:

User user = User.builder()
    .password(password)
    .build();

カスタムセッターは呼び出されないため、パスワードはエンコードされません。これは私を悲しくさせます。

もちろん、カスタムセッターは、直接使用すると呼び出されます。

public void changePassword(String password, User user) {
    user.setPassword(password);
}

Lombokのビルダーにカスタムセッターを使用させるにはどうすればよいですか?

27
Jan Nielsen

@Builder :自分で十分なスケルトンを定義するだけです。特に、LombokはクラスUserBuilderUserフィールドをミラーリングするフィールド、およびビルダーメソッドを生成します。これらのいずれかまたはすべてを自分で提供できます。

@Builder
public class User {
    private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();

    private String username;

    private String password;

    public static class UserBuilder {
        public UserBuilder password(String password) {
            this.password = ENCODER.encode(password);
            return this;
        }
    }
}
45
chrylis

chrylisの答えを受け入れましたが、完全を期すために、カスタマイズと複製を最小限に抑えるいくつかの方法を紹介します。

静的ヘルパーを使用したカスタムセッターおよびビルダー

静的ヘルパーを使用して、カスタム_User.UserBuilder::password_メソッドとカスタム_User::setPassword_メソッドでset password機能のほとんどを共有できます。

_@Data
@Builder
public class User {
    private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();

    private String password = null;

    public void setPassword(String password) {
        this.password = _encodePassword(password);
    }

    public static class UserBuilder {
        public UserBuilder password(String password) {
            this.password = _encodePassword(password)
            return this;
        }
    }

    private static String _encodePassword(String password) {
        Assert.notNull(password);
        return ENCODER.encode(password);
    }
}
_

カスタムセッターとコンストラクター

カスタムコンストラクターは、Lombokで生成されたUser.UserBuilder::build()によって呼び出される_User::setPassword_を使用できます。

_@Data
@Builder
public class User {
    private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();

    private String password = null;

    User(String password) {
        setPassword(password);
    }

    public void setPassword(String password) {
        Assert.notNull(password);
        this.password = ENCODER.encode(password);
    }
}
_

静的ヘルパーを使用したカスタムセッターおよびコンストラクター

または、もう少しエレガントに、カスタムコンストラクターと静的ヘルパーメソッドを使用します。

_@Data
@Builder
public class User {
    private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();

    private String password = null;

    User(String password) {
        _encodePassword(password, this);
    }

    public void setPassword(String password) {
        _encodePassword(password, this);
    }

    private static _encodePassword(String password, User user) {
        Assert.notNull(password);
        user.password = ENCODER.encode(password);
    }
}
_
7
Jan Nielsen

ビルダーのsetメソッドではなくsetPasswordを使用しています。

ここに私のために働いたものがあります:

_import lombok.Builder;
import lombok.Data;

@Builder
@Data
public class User {
    private String username;
    private String password;

    public static class UserBuilder {
        private String password;
        public UserBuilder password(String password ) {
            this.password ="ENCRIYP " +  password;
            return this;
        }
    }

    public static void main(String[] args) {
        System.out.println(User.builder().username("This is my username").password("Password").build().toString());

    }
}
_

結果は次のとおりでした:User(username=This is my username, password=ENCRIYP Password)

3
Bojan Petkovic