我们使用 HashMap 来缓存方法上的注释查找。使用 Spring 的AnnotationUtils.findAnnotation检索注释。不使用缓存会导致性能严重下降。
我们的实现看起来像:
public class SomeService {
// Caches annotations on methods. The value can be null!
private static final Map<Method, MyAnnotation> ANNOTATION_CACHE = new HashMap<Method, MyAnnotation>();
private MyAnnotation findAnnotation(Method m) {
if (ANNOTATION_CACHE.containsKey(m)) {
return ANNOTATION_CACHE.get(m);
}
MyAnnotation a = AnnotationUtils.findAnnotation(m, MyAnnotation.class);
ANNOTATION_CACHE.put(m, a);
return a;
}
public void doSomethingWith(Class<?> clazz) {
for (Method m : clazz.getMethods()) {
MyAnnotation a = findAnnotation(m);
if (a != null) {
// do something with annotation a
}
}
}
}
现在的问题是我是否需要同步对 ANNOTATION_CACHE Map 的访问。可能发生的最糟糕的事情是两个并行线程将相同的 (m, a) 对放入缓存映射中,这不会造成伤害,不是吗?
我的第一个想法是使用 ConcurrentHashMap,但它不允许空值(如果方法没有注释 => null,则此处需要)。使用 Collections.synchronizedMap() 并同步对地图的每次访问也不理想,因为这个 doSomethingWith() 方法被非常频繁地调用。
那么这种情况下是否真的需要同步对HashMap的访问呢?缓存在运行时从不更改,键/值对只插入一次,永远不会被删除,但会被读取多次。
有什么想法吗?