lambda 表达式中的返回类型错误:Mono<User> 无法转换为 Mono<UserDetails>

问题描述 投票:0回答:1

为什么这有效

    @Bean
    public ReactiveUserDetailsService userDetailsService() {
        return username -> {
            Mono<UserDetails> userDetailsMono = Mono.justOrEmpty(userRepository.findByUsername(username));
            return userDetailsMono.switchIfEmpty(Mono.error(() -> new UsernameNotFoundException("No such user: " + username)));
        };
    }

但这不是(我更喜欢作为更简洁的选项)?

    @Bean
    public ReactiveUserDetailsService userDetailsService() {
        return username -> Mono.justOrEmpty(userRepository.findByUsername(username))
                .switchIfEmpty(Mono.error(() -> new UsernameNotFoundException("No such user: " + username)));
    }
Bad return type in lambda expression: Mono<User> cannot be converted to Mono<UserDetails>

User
是我的自定义用户类,它实现了
UserDetails
findByUsername()
返回
Mono<User>

// @Entity etc.
public class User implements UserDetails {
public interface UserRepository extends Repository<User, UUID> {
//...
    Optional<User> findByUsername(String username);
java spring-security spring-webflux
1个回答
0
投票
  • ReactiveUserDetailsService
    的抽象方法
    findByUsername(String username)
    ,返回
    Mono<UserDetails>
    找出它为什么不返回
    Mono<? extends UserDetails>
    。这意味着你的 lambda 也应该返回
    Mono<UserDetails>
  • Mono.justOrEmpty()
    是通用的,并具有此合同:
    <T> Mono<T> justOrEmpty(@Nullable Optional<? extends T> data)
    。它依赖于 Java 的类型推断,但有其局限性
  • 当你写下这段代码时:
    @Bean
    public ReactiveUserDetailsService userDetailsService() {
        return username -> Mono.justOrEmpty(userRepository.findByUsername(username));
    }

justOrEmpty()
的实际返回类型是从包装函数
fetchByUsername()
的返回类型推断出来的。这是
Mono<UserDetails>

  • 当你写下这段代码时:
    @Bean
    public ReactiveUserDetailsService userDetailsService() {
        return username -> {
            Mono<UserDetails> userDetailsMono = Mono.justOrEmpty(userRepository.findByUsername(username));
            return userDetailsMono.switchIfEmpty(Mono.error(() -> new UsernameNotFoundException("No such user: " + username)));
        };
    }

justOrEmpty()
的实际返回类型是根据将结果分配给的变量的类型推断出来的。这又是
Mono<UserDetails>
。从预期返回类型和变量类型进行推断是 Java 类型推断适用于泛型方法的两种最常见方式

  • 当你写下这段代码时
    @Bean
    public ReactiveUserDetailsService userDetailsService() {
        return username -> Mono.justOrEmpty(userRepository.findByUsername(username))
                .switchIfEmpty(Mono.error(() -> new UsernameNotFoundException("No such user: " + username)));
    }

Java 既不能从外部函数的返回类型(不返回

justOrEmpty()
的结果)也不能从变量类型(不分配
justOrEmpty()
的结果)推断出
justOrEmpty()
的返回类型。因此,Java 假定实际返回类型等于被调用函数的返回类型,
findByUsername()
。这是
Optional<User>
(不是
Optional<UserDetails>

  • switchIfEmpty()
    不会改变
    Mono
    的类型,它仍然是
    Mono<User>
    。所以最终 lambda 返回
    Mono<User>
    这与 lambda 应该返回
    Mono<UserDetails>
    不同
  • Mono<User>
    不是
    Mono<UserDetails>
    的子类型,尽管
    User
    UserDetails
    的子类型(Java 的泛型是 invariant
© www.soinside.com 2019 - 2024. All rights reserved.