我的想法用完了,谷歌也帮不上忙。用例看起来很简单,但它在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的持久集合(包含实体)进行操作时,我遇到了同样的问题。我放弃了假设代理对象(集合中的实体)可能已经是代理的问题。
似乎我错了,因为category和所有继承的类都是作为结果转换器传递到hibernate的pojo。
这种行为的原因可能是什么?
你知道吗?
(我使用的是最新的lambdaj-2.4)。
为了满足马里奥的要求
代码是一个简单的枚举。
类别是不同类别的基类,它有代码字段。而且,它是公共静态类,与所有继承类相同(如果重要的话)。
我尽量提供不及格的考试。
再次编辑以提供附加信息。
我的一个朋友看了一下代码,对这个问题提出了新的看法。
我将尝试从一开始就再现我们的演绎之路。
//给定
有一个应用程序分为两部分,第一个基本应用程序(保留模型文件)和Web应用程序(保留与UI连接的文件,如backing bean等)。
我们的类别和代码是模型类,因此位于基础应用程序中。然后,我们有一个支持bean,用于某些web逻辑,特别是该bean或其合作者调用我们的select。
//当
我们正在将应用程序部署到Web服务器!jboss在我的案例中。类是由加载程序读取的,有些我不知道的非常复杂的事情,都是为了让我的应用程序运行。
我做了一些web操作,backing bean的方法被调用
selectFirst(results, having(on(Category.class).getCode(), is(code)));
从应用程序的Web部件。
魔法来了。
我们的category.class和code.class是由unifiedclassloader在应用程序加载时加载的。
我们在(category.class)方法中,category的代理将被构建。一些非常复杂的逻辑被用来实现这一点,最重要的是,代理使用
setThreadsCallbacks(Callback[]callbacks)
方法,但callback.class是从类加载器中获取的。
aCategory.getClass.getClassLoader()
因此,最初加载该类的是类加载器unifiedclassloader。
干净利落地完成了这一切,我们终于打电话给
getFirstInstance()
使用反射浏览代理类以查找:
proxy.getDeclaredMethod(“setThreadScallBacks”,新类[]{callback[].class});
我忽略了这个事实,我不明白
new Class[]{ Callback[].class }
在我们的例子中,重要的是callback.class不是由unifiedclassloader提供的。
应用程序在Web轮胎中执行,因此对callback.class的调用将由Web应用服务器执行。类加载器和重新生成的callback.class将从先前作为参数放入的setThreadScallBacks函数中返回。反思是残酷的。
Category.class != Category.class //these two were provided by different classLoaders
这就是为什么我不能提供失败的测试。(同一类装入器)。
我怀疑那案子有什么解决办法。
最佳答案
我也遇到过类似的问题。(引发的异常相同:java.lang.ClassCastException:xxx$category$$enhancerbycGlib$$xxx不能强制转换为net.sf.cglib.proxy.factory)
在我的例子中,结果是重复的(甚至是三倍的)cglib库有问题。我们有如下:
jboss(4.2.3)库中的cglib.jar
应用程序Web库中的cglib-nodep.jar(WAR文件)
应用程序Web库中的labmdaj-2.4-with-dependencies.jar。
然后,当使用lambda.on(someClass.class)时,我们在cglib的Enhancer
类中得到这个方法:
private static Method getCallbacksSetter(Class type, String methodName) throws NoSuchMethodException {
return type.getDeclaredMethod(methodName, new Class[]{ Callback[].class });
}
其中
methodName = "CGLIB$SET_THREAD_CALLBACKS"
类型是我们的someClass,由
Enhancer
包装。包装类型中存在“cglib$set_thread_callbacks”方法,但getDeclaredMethod()返回空值。在getDeclaredMethod()中,似乎比较了两个
net.sf.cglib.proxy.Callback.class
实例。它们是不同的,因为一个是从cglib.jar(jboss)加载的,另一个是从cglib-nodep.jar(webapp)加载的。解决方案是删除多余的cglib-nodep.jar并用lambda-2.4.jar替换lambda-2.4-with-dependencies.jar。现在所有的cglib类都是从公共位置加载的,问题已经解决了。