Play框架Silhouette移除认证信息时隐式参数异常问题排查
1. 正确调用AuthInfoRepository#remove的方式
你遇到的核心问题是Scala无法自动推断出remove方法的泛型参数T的具体类型,导致它被推断为Nothing,而DelegableAuthInfoRepository没有为Nothing类型配置对应的DAO,所以抛出了配置异常。
解决这个问题的关键是明确指定要删除的AuthInfo类型——因为你用的是CredentialsProvider,对应的AuthInfo类型是CredentialsAuthInfo。有两种简洁的实现方式:
方式一:显式指定泛型类型参数
直接在调用remove时加上类型参数,Scala会自动为你生成对应的ClassTag:
authInfoRepository.remove[CredentialsAuthInfo](LoginInfo(credentialsProvider.id, username))
方式二:手动提供隐式ClassTag
如果你需要更明确地控制,也可以手动传入ClassTag实例:
import scala.reflect.classTag authInfoRepository.remove(LoginInfo(credentialsProvider.id, username))(classTag[CredentialsAuthInfo])
两种方式都能解决类型推断为Nothing的问题,推荐第一种,代码更简洁直观。
2. 隐式ClassTag参数的作用
这个ClassTag是Scala用来绕过Java类型擦除限制的工具。
Java的泛型是编译时的语法糖,运行时会丢失泛型类型信息(也就是类型擦除)。而DelegableAuthInfoRepository是一个委托式仓库,它会根据AuthInfo的不同类型,转发操作给对应的DAO实现(比如CredentialsAuthInfo对应CredentialsAuthInfoDAO)。
为了在运行时知道当前要处理的是哪种具体的AuthInfo类型,就需要ClassTag来保存这个类型的Class信息。当你提供了ClassTag[T],DelegableAuthInfoRepository就能在运行时拿到T的Class对象,从而找到对应的DAO来执行删除操作。
简单来说,ClassTag就是让泛型类型在运行时“可见”,让仓库知道该调用哪个具体的DAO实现。
内容的提问来源于stack exchange,提问作者Cedric Reichenbach

