为什么这有效
@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);
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)