我刚刚开始面向方面编程,并且遇到了一个检查集合中并发修改的示例。但我在理解代码含义时遇到了问题: -
public aspect FailSafeIter {
Map<Iterator,Collection> iterToColl = new HashMap<Iterator,Collection>();
// Create interator
after(Collection c) returning (Iterator i):
call(* Collection.iterator()) && target(c)
{
iterToColl.put(i,c);
}
// Update collection
after(Collection c) returning:
(call(* Collection.add(..)) || call(* Collection.remove(..)) ) && target(c)
{
iterToColl.values().remove(c);
}
// Iterate over collection
before(Iterator i):
call(* Iterator.*()) && target(i)
{
if(!iterToColl.containsKey(i))
throw new ConcurrentModificationException();
}
}
任何人都可以解释上述行的含义以及它如何检测并发修改异常?
答案 0 :(得分:0)
我刚刚修改了您的代码格式,并将注释更改为更具描述性,以便您了解正在发生的事情:
Collection.iterator()
的调用,即advice方法在内部键值映射iterToColl
中记录所有新创建的迭代器及其对应的集合。这是该方面内部记账的第一步。Collection.add(..)
或Collection.remove(..)
的调用,即调用修改集合的方法(这是一个警告,在迭代时不应该这样做)。如果找到一个调用,该通知将从内部映射中删除与此集合相关的所有键值对。Iterator.next()
(这可能是意图),也是Iterator.hasNext()
等无害的方法(这里可能不需要)。如果拦截了这样的调用,则通知会检查是否在内部映射中找到了相关的迭代器。如果找到了,一切都很好,建议什么都不做。否则它会抛出ConcurrentModificationException
,因为它假定在正在进行的迭代期间使用迭代器的集合已被修改。在后一种情况下,该集合将在上述第二个建议中早先从地图中删除。总而言之,这方面非常神秘,只会在非常特殊的情况下工作(如果由于不精确的切入点而导致的话)。国际海事组织有很多选择让它破裂。但无论如何,这是一个有趣的想法,可能适用于简单明了的案例。不过,我还没有测试过。我只是在脑中使用AspectJ解析器来解决它。
我希望这个解释足够了。