为何两段ReactiveUserDetailsService代码一段可行一段报类型转换错?
问题:ReactiveUserDetailsService Bean实现中链式调用的类型不匹配错误
问题场景
实现ReactiveUserDetailsService的Bean时,以下代码可正常运行:
@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接口:
// @Entity etc. public class User implements UserDetails { // ...实现接口方法 }
UserRepository定义:
public interface UserRepository extends Repository<User, UUID> { //... Optional<User> findByUsername(String username); }
原因分析
这是Java泛型类型推断规则导致的差异:
- 第一种写法中,显式声明了变量类型为
Mono<UserDetails>,编译器会自动将Mono.justOrEmpty(Optional<User>)向上转型为Mono<UserDetails>——因为User是UserDetails的实现类,这种赋值合法。 - 第二种链式写法中,编译器会根据
Mono.justOrEmpty的入参Optional<User>,默认推断返回Mono<User>。后续调用switchIfEmpty时会沿用该泛型类型,最终整个链式调用返回Mono<User>,但ReactiveUserDetailsService要求返回Mono<UserDetails>,因此触发类型不匹配错误。
解决办法
在链式调用中显式指定Mono.justOrEmpty的泛型类型,强制编译器推断为Mono<UserDetails>:
@Bean public ReactiveUserDetailsService userDetailsService() { return username -> Mono.<UserDetails>justOrEmpty(userRepository.findByUsername(username)) .switchIfEmpty(Mono.error(() -> new UsernameNotFoundException("No such user: " + username))); }
也可以通过cast()方法显式转换类型:
@Bean public ReactiveUserDetailsService userDetailsService() { return username -> Mono.justOrEmpty(userRepository.findByUsername(username)) .cast(UserDetails.class) .switchIfEmpty(Mono.error(() -> new UsernameNotFoundException("No such user: " + username))); }
内容的提问来源于stack exchange,提问作者Sergey Zolotarev
相关产品推荐
相关产品推荐

