我的想法用完了,谷歌也没有帮助。用例似乎微不足道,但因 ClassCastException 而失败。我不知道我做错了什么。有一个简单的方法可以返回匹配给定类别的第一个元素,看看。
private Category selectElement(List<? extends Category> results, Code code) {
return selectFirst(results, having(on(Category.class).getCode(), is(code)));
}
执行给出了堆栈的顶部:
java.lang.ClassCastException: name.wilu.logic.report.utils.SheetLoader$Category$$EnhancerByCGLIB$$3a35aefc cannot be cast to net.sf.cglib.proxy.Factory
at ch.lambdaj.proxy.ClassImposterizer.createProxy(ClassImposterizer.java:134)
at ch.lambdaj.proxy.ClassImposterizer.imposterise(ClassImposterizer.java:101)
at ch.lambdaj.proxy.ProxyUtil.createProxy(ProxyUtil.java:52)
at ch.lambdaj.function.argument.ArgumentsFactory.createPlaceholder(ArgumentsFactory.java:68)
at ch.lambdaj.function.argument.ArgumentsFactory.registerNewArgument(ArgumentsFactory.java:58)
at ch.lambdaj.function.argument.ArgumentsFactory.createArgument(ArgumentsFactory.java:50)
at ch.lambdaj.function.argument.ArgumentsFactory.createArgument(ArgumentsFactory.java:39)
at ch.lambdaj.Lambda.on(Lambda.java:63)
我在使用 lambdaJ 对 hibernate 的持久集合进行操作时遇到了同样的问题。我放弃了假设已经是代理的代理对象(集合中的实体)可能存在一些问题。看来我错了,因为类别和所有继承的类都是作为结果转换器传递给休眠的 pojos。
这种行为的原因可能是什么?你有什么主意吗?
(我使用的是最新的 lambdaj-2.4)。
添加以满足马里奥的要求
代码是一个简单的枚举。类别是不同类别的基类,它有代码字段。此外,它是公共静态类,与所有继承类相同(如果重要的话)。
我将尝试提供失败的测试。
再次编辑以提供更多信息。 我的一个朋友查看了代码,并对这个问题提出了新的看法。
我将尝试从一开始就重现我们的演绎路径。
// 给定
有一个应用程序分为两部分,第一个基础应用程序(保存模型文件)和 Web 应用程序(保存 UI 连接文件,如 backing beans 等)。 我们的类别和代码是模型类,因此位于基础应用程序中。然后我们有一个支持 bean 服务于一些 web 逻辑,特别是 bean 或其合作者调用我们的 select。
// 什么时候
我们正在将应用程序部署到 Web 服务器!就我而言,JBoss。类由加载器读取,一些我不知道的非常复杂的事情发生了,所有这些都是为了让我的应用程序运行。我做了一些网络操作,然后调用了支持 bean 的方法
selectFirst(results, having(on(Category.class).getCode(), is(code)));
从应用程序的 Web 部分。
魔法来了。我们的 Category.class 和 Code.class 由 UnifiedClassLoader 在应用程序加载时加载。我们在on(Category.class)方法中,并且将构建 Category 的代理。一些真正纠结的逻辑被用来做到这一点,最重要的是,代理是用
setThreadsCallbacks(Callback[]callbacks)
方法,但 Callback.class 取自该类加载器
aCategory.getClass.getClassLoader()
因此,最初加载该类 UnifiedClassLoader 的是一个类加载器。干净地完成所有这些之后,我们终于打电话给
getFirstInstance()
使用反射浏览代理类寻找: Proxy.getDeclaredMethod("setThreadsCallbacks", new Class[]{ Callback[].class });
我忽略了事实,我不明白
new Class[]{ Callback[].class }
在我们的例子中重要的是 Callback.class 不是由 UnifiedClassLoader 提供的。应用程序在网络轮胎中执行,因此对 Callback.class 的调用将通过网络应用程序进行服务器。类加载器和返回的 Callback.class 将与之前作为提到的setThreadsCallbacks函数的参数放置的内容不同。反思残酷地失败了。
Category.class != Category.class //these two were provided by different classLoaders
这就是为什么我无法提供失败的测试。(相同的类加载器)。
我怀疑这种情况有什么解决方案。