1

我怎样才能让 Immutables 生成具有这种类型的类

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 Security 中的重新实现,您应该假定排序需要应用于将传递给 Immutables 构建器的任何集合。

4

1 回答 1

1

鉴于我了解您想要实现的目标,您如何使用 Immutables 注释处理器实现这一目标有很多变化;)

Immutables 支持SortedSet开箱即用,但仅使用自然排序(请参阅@Value.NaturalOrder@Value.ReverseOrder)。如果您想应用特殊的比较器,Immutables 将只允许您自己构建集合并将其设置到构建器上。从示例来看,希望排序是特定于对象实现的东西,所以我将跳到其他选项。

有强大的(但有点容易出错)功能来启用使用@Value.Check方法的对象的规范化/规范化。它在指南中有所描述:http: //immutables.github.io/immutable.html#normalization。但是,由于需要检查集合/集合是否已经排序,因此使用规范化有点复杂。

最后,我将提出另一种更简单的方法,我已将其用于类似目的。@Value.Derived注释允许您在对象构建期间构建数据的替代视图。在这种情况下,将有一个集合用作初始化缓冲区和该数据的计算的替代视图。计算将在构造过程中发生,并且在此之后不可变对象将永远不会改变。我们将使用访问和属性名称使其看起来不错。这是示例:

@Value.不可变
公共抽象类 IdentifiedUserDetails 实现 UserDetails、CredentialsContainer、Identified<UUID> {
    私有静态最终长序列版本UID = 4905378177558522349L;

    公共抽象 UUID getId();
    公共抽象字符串 getUsername();
    公共抽象字符串 getPassword();
    // 为简洁起见省略了其他属性
    // ...

    抽象的@SkipNulls List<GrantedAuthority> authority();

    @Value.Derived
    公共 SortedSet<GrantedAuthority> getAuthorities() {
        返回权限()。流()
                .collect(Collectors.toCollection(() -> {
                    返回新的树集(
                            Comparator.nullsFirst(Comparator.comparing(GrantedAuthority::getAuthority)));
                }));
    }
}

公共静态无效演示(GrantedAuthority ga1,GrantedAuthority ga2){

    IdentifiedUserDetails 详细信息 =
            ImmutableIdentifiedUserDetails.builder()
                    .id(UUID.randomUUID())
                    .username("姓名")
                    .password("字符串")
                    //...
                    .addAuthority(ga1)
                    .addAuthority(ga2)
                    。建造();

    SortedSet<GrantedAuthority> sortedAuthorities = details.getAuthorities();
}

PS@SkipNulls是一种BYOA注释。如果需要,创建它,它会被一个简单的名称识别。

于 2016-12-29T10:50:26.960 回答