2017-02-21 7 views
8

У меня есть пользовательский сеттер в моей Ломбок основе 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); 
    } 

, но когда я использую Ломбок генерироваться строитель:

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

мой пользовательский сеттер не вызывается , и поэтому пароль не закодирован. Меня это огорчает.

Мой заказ сеттер, конечно, вызывается, когда я использую его непосредственно:

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

Что я могу сделать, чтобы строитель Ломбок использовать свой собственный сеттер?

ответ

12

Per 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; 
     } 
    } 
} 
+2

Спасибо, ** chrylis ** - но как 'Person :: setPassword' (от Ломбок' @ Data') и 'Person.PersonBuilder :: password' разделяют Сухая реализация? –

+0

@JanNielsen Вы действительно не можете - точка «Builder» должна препопылять все данные. Часто, фактически, он используется с неизменным классом. Вы можете рассмотреть подход «конструктор», вызывая 'this.setPassword()' из класса 'User' и игнорируя проблемы с кодированием целиком в построителе. – chrylis

+0

@JanNielsen Чем больше я думаю об этом, тем больше, кажется, имеет смысл сделать вызывающего абонента ответственным за кодирование пароля. Слишком много происходит при кодировании в устройстве настройки свойств. Помимо прочего, вы не можете установить хешированный пароль без прямого доступа к полю. – chrylis

0

Вы используете 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)

+0

Спасибо, ** Borjan **! Похоже, что ** chrylis ** избил вас на тот же ответ ... –

2

Я принял chrylis «S ответа, но для полноты картины, вот несколько способов, чтобы свести к минимуму настройки и дублирования.

Пользовательские сеттер и строитель со статическим помощником

Статический помощник может быть использован для акций большинства набора пароля функциональности через метод пользовательских User.UserBuilder::password и метод пользовательских User::setPassword:

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

Пользовательский сеттер и конструктор

Пользовательский конструктор может использовать User::setPassword, который вызывается Ломбок генерироваться User.UserBuilder::build():

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