如何建议让 Immutables 以这种方式构建此对象
How would it be advised to get Immutables to build this object with this sort
如何让 Immutables 生成具有这种
的 class
public class IdentifiedUserDetails implements UserDetails, CredentialsContainer, Identified<UUID> {
private static final long serialVersionUID = 4905378177558522349L;
private final UUID id;
private final String username;
private final Set<GrantedAuthority> authorities;
private boolean accountNonExpired = true;
private boolean accountNonLocked = true;
private boolean credentialsNonExpired = true;
private boolean enabled = true;
private String password;
IdentifiedUserDetails( final UUID id, final String username, final String password ) {
this.id = Objects.requireNonNull( id );
this.username = Objects.requireNonNull( username );
this.password = Objects.requireNonNull( password );
this.authorities = Collections.unmodifiableSet( sortAuthorities( Collections.emptySet() ) );
}
private static SortedSet<GrantedAuthority> sortAuthorities(
final Collection<? extends GrantedAuthority> authorities ) {
// Ensure array iteration order is predictable (as per
// UserDetails.getAuthorities() contract and SEC-717)
return authorities.stream()
.filter( Objects::nonNull )
.collect( Collectors.toCollection( () -> {
return new TreeSet<GrantedAuthority>(
Comparator.nullsFirst( Comparator.comparing( GrantedAuthority::getAuthority ) ) );
} ) );
}
}
注意:空集是从某些外部数据源传入的真实集的占位符,我还没有开始填充它,但我会在某个时候填充,并且排序是在 spring 安全性中,您应该假定排序需要应用于将传递给不可变构建器的任何集合。
鉴于我理解您想要实现的目标,您可以使用不可变注释处理器实现这一目标的方式有很多变体;)
Immutables 支持开箱即用的 SortedSet
,但仅使用自然排序(参见 @Value.NaturalOrder
和 @Value.ReverseOrder
)。如果你想应用特殊的比较器,Immutables 将只允许你自己构建集合并将其设置到构建器上。从这个例子来看,希望排序是特定于对象实现的东西,所以我会跳到其他选项。
使用 @Value.Check
方法启用对象的 normalization/canonicalization 功能非常强大(但有些容易出错)。指南中对其进行了描述:http://immutables.github.io/immutable.html#normalization。但是,使用规范化有点复杂,因为需要检查 set/collection 是否已经排序。
最后,我会提出另一种更简单的方法,我已将其用于类似目的。 @Value.Derived
注释允许您在对象构建期间构建数据的替代视图。在这种情况下,将使用集合作为初始化缓冲区和该数据的计算替代视图。计算将在构造期间发生,并且不可变对象在那之后永远不会改变。我们将尝试使用访问名和属性名来使它看起来更漂亮。这是示例:
@Value.Immutable
public abstract class IdentifiedUserDetails implements UserDetails, CredentialsContainer, Identified<UUID> {
private static final long serialVersionUID = 4905378177558522349L;
public abstract UUID getId();
public abstract String getUsername();
public abstract String getPassword();
// other attributes omitted for brevity
// ...
abstract @SkipNulls List<GrantedAuthority> authority();
@Value.Derived
public SortedSet<GrantedAuthority> getAuthorities() {
return authority().stream()
.collect(Collectors.toCollection(() -> {
return new TreeSet(
Comparator.nullsFirst(Comparator.comparing(GrantedAuthority::getAuthority)));
}));
}
}
public static void demonstration(GrantedAuthority ga1, GrantedAuthority ga2) {
IdentifiedUserDetails details =
ImmutableIdentifiedUserDetails.builder()
.id(UUID.randomUUID())
.username("Name")
.password("String")
//...
.addAuthority(ga1)
.addAuthority(ga2)
.build();
SortedSet<GrantedAuthority> sortedAuthorities = details.getAuthorities();
}
P.S。 @SkipNulls
是一种 BYOAnnotation。如果需要,创建它,它会被一个简单的名字识别。
如何让 Immutables 生成具有这种
的 classpublic class IdentifiedUserDetails implements UserDetails, CredentialsContainer, Identified<UUID> {
private static final long serialVersionUID = 4905378177558522349L;
private final UUID id;
private final String username;
private final Set<GrantedAuthority> authorities;
private boolean accountNonExpired = true;
private boolean accountNonLocked = true;
private boolean credentialsNonExpired = true;
private boolean enabled = true;
private String password;
IdentifiedUserDetails( final UUID id, final String username, final String password ) {
this.id = Objects.requireNonNull( id );
this.username = Objects.requireNonNull( username );
this.password = Objects.requireNonNull( password );
this.authorities = Collections.unmodifiableSet( sortAuthorities( Collections.emptySet() ) );
}
private static SortedSet<GrantedAuthority> sortAuthorities(
final Collection<? extends GrantedAuthority> authorities ) {
// Ensure array iteration order is predictable (as per
// UserDetails.getAuthorities() contract and SEC-717)
return authorities.stream()
.filter( Objects::nonNull )
.collect( Collectors.toCollection( () -> {
return new TreeSet<GrantedAuthority>(
Comparator.nullsFirst( Comparator.comparing( GrantedAuthority::getAuthority ) ) );
} ) );
}
}
注意:空集是从某些外部数据源传入的真实集的占位符,我还没有开始填充它,但我会在某个时候填充,并且排序是在 spring 安全性中,您应该假定排序需要应用于将传递给不可变构建器的任何集合。
鉴于我理解您想要实现的目标,您可以使用不可变注释处理器实现这一目标的方式有很多变体;)
Immutables 支持开箱即用的 SortedSet
,但仅使用自然排序(参见 @Value.NaturalOrder
和 @Value.ReverseOrder
)。如果你想应用特殊的比较器,Immutables 将只允许你自己构建集合并将其设置到构建器上。从这个例子来看,希望排序是特定于对象实现的东西,所以我会跳到其他选项。
使用 @Value.Check
方法启用对象的 normalization/canonicalization 功能非常强大(但有些容易出错)。指南中对其进行了描述:http://immutables.github.io/immutable.html#normalization。但是,使用规范化有点复杂,因为需要检查 set/collection 是否已经排序。
最后,我会提出另一种更简单的方法,我已将其用于类似目的。 @Value.Derived
注释允许您在对象构建期间构建数据的替代视图。在这种情况下,将使用集合作为初始化缓冲区和该数据的计算替代视图。计算将在构造期间发生,并且不可变对象在那之后永远不会改变。我们将尝试使用访问名和属性名来使它看起来更漂亮。这是示例:
@Value.Immutable public abstract class IdentifiedUserDetails implements UserDetails, CredentialsContainer, Identified<UUID> { private static final long serialVersionUID = 4905378177558522349L; public abstract UUID getId(); public abstract String getUsername(); public abstract String getPassword(); // other attributes omitted for brevity // ... abstract @SkipNulls List<GrantedAuthority> authority(); @Value.Derived public SortedSet<GrantedAuthority> getAuthorities() { return authority().stream() .collect(Collectors.toCollection(() -> { return new TreeSet( Comparator.nullsFirst(Comparator.comparing(GrantedAuthority::getAuthority))); })); } } public static void demonstration(GrantedAuthority ga1, GrantedAuthority ga2) { IdentifiedUserDetails details = ImmutableIdentifiedUserDetails.builder() .id(UUID.randomUUID()) .username("Name") .password("String") //... .addAuthority(ga1) .addAuthority(ga2) .build(); SortedSet<GrantedAuthority> sortedAuthorities = details.getAuthorities(); }
P.S。 @SkipNulls
是一种 BYOAnnotation。如果需要,创建它,它会被一个简单的名字识别。