2017-08-17 102 views
1

我试着在弹簧4.3上使用ehcache3项目。 我配置的缓存管理器:Spring Ehcache3导致与键型和值型的异常

<cache:annotation-driven /> 
<bean id="cacheManager" class="org.springframework.cache.jcache.JCacheCacheManager"> 
     <property name="cacheManager"> 
      <bean class="org.springframework.cache.jcache.JCacheManagerFactoryBean"> 
       <property name="cacheManagerUri" value="classpath:ehcache.xml"/> 
      </bean> 
     </property> 
</bean> 

而且ehcache.xml中

<config 
     xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' 
     xmlns='http://www.ehcache.org/v3' 
     xmlns:jsr107='http://www.ehcache.org/v3/jsr107' 
     xsi:schemaLocation=" 
     http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd 
     http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd" > 
    <service> 
     <jsr107:defaults enable-statistics="true" enable-management="true"/> 
    </service> 
    <cache alias="customerSettings"> 
     <key-type>java.lang.Long</key-type> 
     <expiry> 
      <none/> 
     </expiry> 
     <resources> 
      <heap>500</heap> 
     </resources> 
    </cache> 
</config> 

但是当我部署的项目,我有一个例外:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cacheManager' defined in ServletContext resource [/WEB-INF/spring/root-context.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Cache [customerSettings] specifies key/value types. Use getCache(String, Class, Class) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351) 
    ... 100 more 
Caused by: java.lang.IllegalArgumentException: Cache [customerSettings] specifies key/value types. Use getCache(String, Class, Class) 
    at org.ehcache.jsr107.Eh107CacheManager.getCache(Eh107CacheManager.java:297) 
    at org.springframework.cache.jcache.JCacheCacheManager.loadCaches(JCacheCacheManager.java:105) 
    at org.springframework.cache.support.AbstractCacheManager.initializeCaches(AbstractCacheManager.java:61) 
    at org.springframework.cache.support.AbstractCacheManager.afterPropertiesSet(AbstractCacheManager.java:50) 
    at org.springframework.cache.jcache.JCacheCacheManager.afterPropertiesSet(JCacheCacheManager.java:97) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) 
    ... 107 more 

如果我删除:

<key-type>java.lang.Long</key-type> 

它工作正常,但缓存的keyType是Object, 需要做什么,我可以使用自己的键类型和值类型?

回答

0

正如你可以在org.springframework.cache.jcache.JCacheCacheManager的源中看到的那样,Spring不理解它应该使用方法getCache(String,Class,Class)而不是简单的getCache(String)。更确切地说,这个类对getCache(String,Class,Class)一无所知。

所以,你有三种方式:

  1. 什么都不做的获取过程中,把操作的缓存使用equals()和可能的hashCode()从实类的关键方法。如果您使用直接访问缓存而不是通过注释进行声明性访问,则只有在显式类型转换中才会感到不适。

  2. 扩展此类并研究它以理解这些缓存配置功能。

  3. 看看另一个可能知道这些设置的CacheManager。

0

好你要砍一点点:

编写自定义CacheManager,并用它在你的XML配置:

<bean id="cacheManager" class="your.path.MyCustomLongObjectJCacheManager"> 
     <property name="cacheManager"> 
      <bean class="org.springframework.cache.jcache.JCacheManagerFactoryBean"> 
       <property name="cacheManagerUri" value="classpath:ehcache.xml"/> 
      </bean> 
     </property> 
</bean> 

下面是一些(伪)代码:

public class MyCustomLongObjectJCacheManager extends JCacheCacheManager{ 

    @Override 
    protected Collection<Cache> loadCaches() { 

     javax.cache.CacheManager cacheManager = getCacheManager(); 

     Collection<Cache> caches = new LinkedHashSet<Cache>(); 
     for (String cacheName : getCacheManager().getCacheNames()) { 

      if("customerSettings".equals(cacheName)){ // or manager instance of Eh107CacheManager... 
       javax.cache.Cache<Long, Object> jcache = cacheManager.getCache(cacheName, Long.class, Object.class); 
       caches.add(new MyCustomAdaptingCache(jcache, isAllowNullValues())); 
      } else { 
       javax.cache.Cache<Object, Object> jcache = cacheManager.getCache(cacheName); 
       caches.add(new JCacheCache(jcache, isAllowNullValues())); 
      } 

     } 
     return caches; 
    } 

    @Override 
    protected Cache getMissingCache(String cacheName) { 
     // Check the JCache cache again (in case the cache was added at runtime) 

     javax.cache.CacheManager cacheManager = getCacheManager(); 

     if("customerSettings".equals(cacheName)){ 
      javax.cache.Cache<Long, Object> jcache = cacheManager.getCache(cacheName, Long.class, Object.class); 
      return new MyCustomAdaptingCache(jcache, isAllowNullValues()); 
     } 

     javax.cache.Cache<Object, Object> jcache = getCacheManager().getCache(cacheName); 
     if (jcache != null) { 
      return new JCacheCache(jcache, isAllowNullValues()); 
     } 
     return null; 
    } 


} 


public static class MyCustomAdaptingCache extends AbstractValueAdaptingCache { 

    private final javax.cache.Cache<Long, Object> cache; 

    public MyCustomAdaptingCache(javax.cache.Cache<Long, Object> jcache) { 
     this(jcache, true); 
    } 

    public MyCustomAdaptingCache(javax.cache.Cache<Long, Object> jcache, boolean allowNullValues) { 
     super(allowNullValues); 
     Assert.notNull(jcache, "Cache must not be null"); 
     this.cache = jcache; 
    } 

    @Override 
    public final String getName() { 
     return this.cache.getName(); 
    } 

    @Override 
    public final javax.cache.Cache<Long, Object> getNativeCache() { 
     return this.cache; 
    } 

    @Override 
    protected Object lookup(Object key) { 
     return this.cache.get((Long)key); 
    } 

    @Override 
    public <T> T get(Object key, Callable<T> valueLoader) { 
     try { 
      return this.cache.invoke((Long)key, new ValueLoaderEntryProcessor<T>(), valueLoader); 
     } 
     catch (EntryProcessorException ex) { 
      throw new ValueRetrievalException(key, valueLoader, ex.getCause()); 
     } 
    } 

    @Override 
    public void put(Object key, Object value) { 
     this.cache.put((Long)key, toStoreValue(value)); 
    } 

    @Override 
    public ValueWrapper putIfAbsent(Object key, Object value) { 
     boolean set = this.cache.putIfAbsent((Long)key, toStoreValue(value)); 
     return (set ? null : get(key)); 
    } 

    @Override 
    public void evict(Object key) { 
     this.cache.remove((Long)key); 
    } 

    @Override 
    public void clear() { 
     this.cache.removeAll(); 
    } 

    private class ValueLoaderEntryProcessor<T> implements EntryProcessor<Long, Object, T> { 

     @SuppressWarnings("unchecked") 
     @Override 
     public T process(MutableEntry<Long, Object> entry, Object... arguments) 
       throws EntryProcessorException { 
      Callable<T> valueLoader = (Callable<T>) arguments[0]; 
      if (entry.exists()) { 
       return (T) fromStoreValue(entry.getValue()); 
      } 
      else { 
       T value; 
       try { 
        value = valueLoader.call(); 
       } 
       catch (Exception ex) { 
        throw new EntryProcessorException("Value loader '" + valueLoader + "' failed " + 
          "to compute value for key '" + entry.getKey() + "'", ex); 
       } 
       entry.setValue(toStoreValue(value)); 
       return value; 
      } 
     } 
    } 

} 

祝你好运。

相关问题