阅读spring的aop部分源码,AdvisedSupport这个类中把拦截器链放在一个ConcurrentHashMap中,作为缓存,这里考虑到并发因素显然不能使用hashmap,hashtable也许也可以,可以尝试一把。
// 初始化拦截器链缓存
private void initMethodCache() {
this.methodCache = new ConcurrentHashMap<MethodCacheKey, List<Object>>(32);
}
...
private static class MethodCacheKey {
private final Method method;
private final int hashCode;
public MethodCacheKey(Method method) {
this.method = method;
this.hashCode = method.hashCode();
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
MethodCacheKey otherKey = (MethodCacheKey) other;
return (this.method == otherKey.method);
}
@Override
public int hashCode() {
return this.hashCode;
}
}
可以看到key是一个私有内部类对象,根据Map的机制 ,put时会首先进行hashcode的比较,相同再根据 equals的结果判断是否key相同,决定能不能put。
hashcode()直接使用的是method的hashcode,equals()也是比较的method的地址,显然这个缓存map完全依赖于method变量,所以他必须是不可变的,如果提供了set方法,可能会导致key-value在放入map之后,key的hashcode发生了改变,这会导致数据的丢失,这也是把自定义对象作为Map的key时需要注意的。