Scala调用处理程序导致ClassCastException
我正在尝试实现一个代理模式,以便在必要时可以在封面下动态交换底层实例,并使用扩展方法触发交换。我以前在Java中实现过,但在Scala中遇到了问题 这是我的设想:Scala调用处理程序导致ClassCastException,scala,reflection,proxy,proxy-pattern,Scala,Reflection,Proxy,Proxy Pattern,我正在尝试实现一个代理模式,以便在必要时可以在封面下动态交换底层实例,并使用扩展方法触发交换。我以前在Java中实现过,但在Scala中遇到了问题 这是我的设想: class Client { ...library code... } trait DynamicClient extends Client { def swap: Client } class Provider extends Provider[DynamicClient] { def get():DynamicCli
class Client { ...library code... }
trait DynamicClient extends Client {
def swap: Client
}
class Provider extends Provider[DynamicClient] {
def get():DynamicClient {
java.lang.reflect.Proxy.newProxyInstance(
classOf[DynamicClient].getClassLoader,
Array(classOf[DynamicClient]),
handler)
.asInstanceOf[DynamicClient]
}
}
class DynamicClientHandler extends java.lang.reflect.InvocationHandler {
var client:Client = createNewClient()
def swap(): {
client = createNewClient()
client
}
def createNewClient():Client: { ... }
def invoke(proxy: AnyRef, method: java.lang.reflect.Method, args: Array[AnyRef]): AnyRef = {
method.getDeclaringClass match {
case dyn if dyn == classOf[DynamicClient] => swap()
case _ => method.invoke(client, args: _*)
}
}
}
现在的问题是:当我从DynamicClient或代理对象上的对象调用方法时,它们工作得很好
val dynamicClient = injector.instanceOf[DynamicClient]
val initial = dynamicClient.client
val client = dynamicClient.swap()
val dynamicClient.toString // "Client@1234" (Object impl of toString via client instance)
assert(client != initial) //passes just fine, the underlying client is re-initialized
对属于客户机类的方法的任何调用在到达调用处理程序之前都会失败
//Both of the following scenarios fail independently of the other
//ERROR:
dynamicClient.asInstanceOf[Client]
//ERROR:
dynamicClient.doSomeClientMethod()
对于此异常跟踪:
java.lang.ClassCastException: com.sun.proxy.$Proxy22 cannot be cast to Client
为什么我会得到这个cast异常?与Java方式相比,Scala是否有更好的方式来处理代理调用处理?Ok。我试图让你的例子真正具有可复制性,现在是:
import java.lang.reflect.{Method, Proxy}
class Client
trait DynamicClient extends Client {
def swap: Client
}
def mkClient =
Proxy.newProxyInstance(
classOf[Client].getClassLoader,
Array(classOf[DynamicClient]),
new DynamicClientHandler
).asInstanceOf[DynamicClient]
class DynamicClientHandler extends java.lang.reflect.InvocationHandler {
val client = new Client{}
def invoke(proxy: AnyRef, method: Method, args: Array[AnyRef]): AnyRef =
if (method.getDeclaringClass == classOf[DynamicClient])
swap
else method.invoke(client, args: _*)
def swap = createNewClient
def createNewClient = mkClient
}
mkClient.swap
只要您在客户机
的定义中将类
更改为特征
,此示例就会生效
为什么??因为从trait
扩展class
确实是一个限制,它只在scala编译器中工作。因此,从java的角度来看,接口动态客户端
仍然与类客户端
没有任何共同之处,正如反射错误所说的那样
因此,您不能真正创建
类的代理
,应该考虑一些解决方法。好的。我试图让你的例子真正具有可复制性,现在是:
import java.lang.reflect.{Method, Proxy}
class Client
trait DynamicClient extends Client {
def swap: Client
}
def mkClient =
Proxy.newProxyInstance(
classOf[Client].getClassLoader,
Array(classOf[DynamicClient]),
new DynamicClientHandler
).asInstanceOf[DynamicClient]
class DynamicClientHandler extends java.lang.reflect.InvocationHandler {
val client = new Client{}
def invoke(proxy: AnyRef, method: Method, args: Array[AnyRef]): AnyRef =
if (method.getDeclaringClass == classOf[DynamicClient])
swap
else method.invoke(client, args: _*)
def swap = createNewClient
def createNewClient = mkClient
}
mkClient.swap
只要您在客户机
的定义中将类
更改为特征
,此示例就会生效
为什么??因为从trait
扩展class
确实是一个限制,它只在scala编译器中工作。因此,从java的角度来看,接口动态客户端
仍然与类客户端
没有任何共同之处,正如反射错误所说的那样
因此,您不能真正创建类的代理
,应该考虑一些解决方法。我认为您的代码包含一些错误,特征
s,我相信,不能扩展类
esI相信您是错的,但这肯定可能是问题所在。我只是想知道为什么我认为你的代码有一些不准确的地方,trait
s,我认为,不能extend
class
esI相信你错了,但这肯定是问题所在。我只是想知道为什么