在Lombok的构建器中使用自定义setter

时间:2017-02-21 23:23:11

标签: java lombok

我在基于Lombok的POJO中有一个自定义setter:

u.LastName LIKE 'B%'

但是当我使用Lombok生成的构建器时:

@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);
    }

我的自定义setter未被调用,因此密码未被编码。这让我很伤心。

我的自定义setter当然是在我直接使用时调用的:

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

如果让Lombok的构建器使用我的自定义setter,我该怎么办?

4 个答案:

答案 0 :(得分:42)

the documentation for @Builder:自己定义足够的骨架。特别是,Lombok将生成一个类UserBuilder,镜像User字段的字段和构建器方法,您可以自己提供任何或所有这些。

@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;
        }
    }
}

答案 1 :(得分:2)

您正在使用setPassword而不是构建器的set方法。

这对我有用:

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)

答案 2 :(得分:2)

并不是真正的问题答案,而是一个边缘案例,使我花了很多时间来查找问题。
如果在具有Builder值的字段上具有Builder.Default且具有自定义设置器,则生成的构建器类中的字段名称与原始字段不同。实际上,您将有两个字段而不是一个:password$valuepassword$set
不过,您可以通过以下方式在自定义设置器中使用它们:

public UserBuilder password(String password) {
  this.password$value = ENCODER.encode(password);
  this.password$set = true;
  return this;
}

棘手的部分是,如果您使用origianl字段名,则Intellij IDEA不会对此发出警告(好像一切都很好,但是当然不会编译)。已经向插件提交了错误报告。

答案 3 :(得分:0)

我在工作中遇到过这种情况。下面是我想出来的。这个想法是覆盖 Lombok 的 protected User(User.UserBuilder b) 方法

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

    private String password;
    private Integer otherField;

    protected User(final User.UserBuilder<?, ?> b) {
        setPassword(b.password);
        otherField = b.otherField;
    }

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