背景
这是我的工作(简化)GenericDao界面,由 any 实现DomainDao:
GenericDao.java
@NoRepositoryBean
public interface GenericDao<E extends Persistable<K>, K extends Serializable> extends JpaRepository<E, K> {
    public List<E> findAll();
    public E persist(E entity);
}
GenericDaoImpl.java
public class GenericDaoImpl<E extends Persistable<K>, K extends Serializable> extends SimpleJpaRepository<E, K> implements GenericDao<E, K> {
    private final JpaEntityInformation<E, ?> entityInformation;
    private final EntityManager em;
    private final Class<E> type;
    public GenericDaoImpl(JpaEntityInformation<E, ?> entityInformation, EntityManager em) {
        super(entityInformation, em);
        this.entityInformation = entityInformation;
        this.em = em;
        this.type = entityInformation.getJavaType();
    }
    @Override
    public List<E> findAll() {
        return super.findAll();
    }
    @Override
    @Transactional
    public E persist(E entity) {
        if (entityInformation.isNew(entity) || !EntityUtils.isPrimaryKeyGenerated(type) && !em.contains(entity)) {
            em.persist(entity);
        }
        return entity;
    }
}
例如,要管理域Foo和Bar,您只需要创建两个接口,如下所示:
FooDao.java
public interface FooDao extends GenericDao<Foo, Integer> {
}
巴道.java
public interface BarDao extends GenericDao<Bar, Integer> {
}
的@Autowired注解Spring将自动实例化GenericDaoImpl具有良好实体和主键类型的 a。
问题
我现在正在尝试使用 EhCache 和EhCache Spring Annotations模型在我的 DAO 上添加一个缓存过程。
GenericDao.java
@NoRepositoryBean
public interface GenericDao<E extends Persistable<K>, K extends Serializable> extends JpaRepository<E, K> {
    @Cacheable(cacheName = "dao")
    public List<E> findAll();
    @TriggersRemove(cacheName = "dao")
    public E persist(E entity);
}
应用程序上下文.xml
<ehcache:annotation-driven cache-manager="ehCacheManager" />    
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
ehcache.xml
<cache name="dao"
    eternal="false"
    maxElementsInMemory="10000"
    overflowToDisk="false"
    timeToIdleSeconds="86400"
    timeToLiveSeconds="86400"
    memoryStoreEvictionPolicy="LFU" />
使用 , 的问题GenericDao是缓存应该相互DomainDao独立地管理。例如,在当前配置下,如果我调用fooDao.findAll(), 然后barDao.persist(new Bar()),生成的缓存fooDao.findAll()将被重置,因为会使用相同的缓存(即<cache name="dao" />),而它不应该使用。
小径
我尝试实现自己的CacheKeyGenerator,这将考虑到调用的类型DomainDao:
应用程序上下文.xml
<ehcache:annotation-driven cache-manager="ehCacheManager" default-cache-key-generator="daoCacheKeyGenerator" />    
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
<bean id="daoCacheKeyGenerator" class="myapp.dao.support.DaoCacheKeyGenerator" />
DaoCacheKeyGenerator.java
public class DaoCacheKeyGenerator implements CacheKeyGenerator<DaoCacheKey> {
    @Override
    public DaoCacheKey generateKey(MethodInvocation methodInvocation) {
        Class<?> clazz = methodInvocation.getThis().getClass().getInterfaces()[0];
        Method method = methodInvocation.getMethod();
        String methodName = method.getName();
        Class<?>[] parameterClasses = method.getParameterTypes();
        return new DaoCacheKey(clazz, methodName, parameterClasses);
    }
    @Override
    public DaoCacheKey generateKey(Object... data) {
        return null;
    }
}
DaoCacheKey.java
public class DaoCacheKey implements Serializable {
    private static final long serialVersionUID = 338466521373614710L;
    private Class<?> clazz;
    private String methodName;
    private Class<?>[] parameterClasses;
    public DaoCacheKey(Class<?> clazz, String methodName, Class<?>[] parameterClasses) {
        this.clazz = clazz;
        this.methodName = methodName;
        this.parameterClasses = parameterClasses;
    }
    @Override
    public boolean equals(Object obj) { // <-- breakpoint
        if (obj instanceof DaoCacheKey) {
            DaoCacheKey other = (DaoCacheKey) obj;
            if (clazz.equals(other.clazz)) {
                // if @TriggersRemove, reset any cache generated by a find* method of the same DomainDao
                boolean removeCache = !methodName.startsWith("find") && other.methodName.startsWith("find");
                // if @Cacheable, check if the result has been previously cached
                boolean getOrCreateCache = methodName.equals(other.methodName) && Arrays.deepEquals(parameterClasses, other.parameterClasses);
                return removeCache || getOrCreateCache;
            }
        }
        return false;
    }
    @Override
    public int hashCode() { // <-- breakpoint
        return super.hashCode();
    }
}
上面的问题DaoCacheKey是该equals方法从未被调用(至少程序永远不会中断),但是该方法hashCode确实如此,因此无法应用该算法。
问题
有没有人已经管理过这样的缓存?如果是怎么办?我的尝试是否相关?如果是,如何使equals方法被调用,而不是那个hashCode?通过扩展现有的CacheKeyGenerator? 如果是,是哪一个?