代码如下:
/** * 判断当前流程实例上下文中,是否存在Blocking(阻挡性)的任务 * 规则 * 1.任务未结束 * 2.任务是必办理的 * 3.当前任务实例的token和执行上下文的token一致 * @param token * @return */ public boolean hasBlockingTaskInstances(FlowToken token) { boolean hasBlockingTasks = false; System.out.println("LOC_1 :" + token.getId()); Set<TaskInstance> taskInstances = flowInstance.getTaskInstances(); if (taskInstances!=null) { Iterator<TaskInstance> iter = taskInstances.iterator(); while ( (iter.hasNext()) && (!hasBlockingTasks)) {System.out.println("LOC_2 : " + taskInstance.getFlowToken().getId());System.out.println("LOC_3 : " + token == taskInstance.getFlowToken());System.out.println("LOC_4 : " + token.equals(taskInstance.getFlowToken()); TaskInstance taskInstance = (TaskInstance) iter.next(); if ( (! taskInstance.hasEnded()) //任务未结束 && (taskInstance.getIsBlocking()) //任务是必办理的 && (token!=null) && (token.equals(taskInstance.getFlowToken())) ) { hasBlockingTasks = true; } } } return hasBlockingTasks; }
[b][size=large]
[color=red]上述的 LOC_1 处和 LOC_2 处打印的ID完全相等, LOC_3处输出true(说明对象地址相同),BUT~~ LOC_4处输出是false;[/color][/size][/b]
给出FlowToken的equals实现
/* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof FlowToken)) return false; final FlowToken other = (FlowToken) obj; if (id == null || other.id == null) { return false; } else if (!id.equals(other.id)) return false; return true; }
跟踪发现,实际进入equals的obj参数根本不是外面传入的那个token对象,中间过程被Hinernate的CGLIBLazyInitializer做了代理处理,发生了底层对象的变换。
开始大家都打死不信有这样的BUG,经过对jvm线程和变量编号的反复跟踪,BUG每次都重现。确认CGLIBLazyInitializer确有问题,但目前在国内互联网上没有找到相同的案例。这里提出,供javaeye上的大牛商讨!
如果我们一群人的诊断是对的,hibernate就隐藏了一个相当恐怖的bug咯!!!