5

我正在编写一个 webapp,并尝试缓存一些从控制器调用的 pojo。

当我尝试使用 org.springframework.cache.annotation.Cacheable 时,我无法得到任何工作,所以我切换到 com.googlecode.ehcaceh.annotations.Cacheable,但我仍然无法将其缓存。

我的代码如下所示:

@Controller
 public class Conttroller {
    @RequestMapping(method = RequestMethod.GET)....
    public Person getPerson(String id) {
        LOG.debug("Trying to get resource...);
        Person person = personService.detect(id);
        LOG.debug("got person");

服务看起来像:

public class PersonService {

@Cacheable(cacheName="deviceCache") 
public Person detect(String id) {
LOG.debug("cache missed")

我的 applicationContext 看起来像

<context:component-scan base-package="com.mycompany" />


         <ehcache:annotation-driven cache-manager="ehCacheManager" />
         <bean id="cacheManager"      class="org.springframework.cache.ehcache.EhCacheCacheManager">
            <property name="cacheManager">
                <ref bean="ehCacheManager" />
            </property>
        </bean>
        <bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:configLocation="/META-INF/ehcache.xml" />

我的 ehcache 看起来像:

<defaultCache eternal="false" maxElementsInMemory="1000"
    overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"
    timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>

<cache name="deviceCache"
    maxElementsInMemory="100" overflowToDisk="false" diskPersistent="false"
    timeToIdleSeconds="0" timeToLiveSeconds="300"
    memoryStoreEvictionPolicy="LRU" />

有趣的是它在我的单元测试中缓存得很好......

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:META-INF/applicationContext-test.xml"})
public class PersonServiceTest {

private static final Logger LOG = LoggerFactory.getLogger(PersonServiceTest.class);
@Test
public void testCache() {
    LOG.debug("Getting person...");
    Device detect = personService.detect("test");
    LOG.debug("Getting person again ...");
    detect = personService.detect("test");
    LOG.debug("Done");
}

产生:

    13:45:02.885 [main] DEBUG PersonServiceTest - Getting person...
13:45:02.887 [main] DEBUG c.g.e.a.i.CacheAttributeSourceImpl - Adding CACHE advised method 'detect' with attribute: CacheableAttributeImpl [cacheInstanceResolver=com.googlecode.ehcache.annotations.resolver.SingletonCacheableCacheResolver@5c2bfdff, cacheKeyGenerator=HashCodeCacheKeyGenerator [includeMethod=true, includeParameterTypes=true, useReflection=false, checkforCycles=false], parameterMask=ParameterMask [mask=[]]]
13:45:02.889 [main] DEBUG c.g.e.a.i.EhCacheInterceptor - Generated key '-1043428721379252' for invocation: ReflectiveMethodInvocation: public abstract com.mycompany.Person com.mycompany.PersonServiceImpl.detect(java.lang.String); target is of class [com..mycompany.PersonServiceImpl]
13:45:02.889 [main] DEBUG PersonServiceTest - Missed 
13:45:02.927 [main] DEBUG PersonServiceTest  - Getting person again ...
13:45:02.927 [main] DEBUG c.g.e.a.i.EhCacheInterceptor - Generated key '-1043428721379252' for invocation: ReflectiveMethodInvocation:
13:45:02.927 [main] DEBUG PersonServiceTest  - Done

但是我的战争(通过tomcat7/eclipse wtp运行)的输出是:

   DEBUG net.sf.ehcache.config.ConfigurationFactory Configuring ehcache from InputStream
DEBUG net.sf.ehcache.config.BeanHandler Ignoring ehcache attribute xmlns:xsi
DEBUG net.sf.ehcache.config.BeanHandler Ignoring ehcache attribute xsi:noNamespaceSchemaLocation
DEBUG net.sf.ehcache.util.PropertyUtil propertiesString is null.
DEBUG net.sf.ehcache.config.ConfigurationHelper No CacheManagerEventListenerFactory class specified. Skipping...
DEBUG net.sf.ehcache.Cache No BootstrapCacheLoaderFactory class specified. Skipping...
DEBUG net.sf.ehcache.Cache CacheWriter factory not configured. Skipping...
DEBUG net.sf.ehcache.config.ConfigurationHelper No CacheExceptionHandlerFactory class specified. Skipping...
DEBUG net.sf.ehcache.Cache No BootstrapCacheLoaderFactory class specified. Skipping...
DEBUG net.sf.ehcache.Cache CacheWriter factory not configured. Skipping...
DEBUG net.sf.ehcache.config.ConfigurationHelper No CacheExceptionHandlerFactory class specified. Skipping...
DEBUG net.sf.ehcache.store.MemoryStore Initialized net.sf.ehcache.store.NotifyingMemoryStore for deviceCache
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Pass-Through Statistic: LOCAL_OFFHEAP_SIZE
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Pass-Through Statistic: LOCAL_OFFHEAP_SIZE_BYTES
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Pass-Through Statistic: LOCAL_DISK_SIZE
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Pass-Through Statistic: LOCAL_DISK_SIZE_BYTES
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Pass-Through Statistic: WRITER_QUEUE_LENGTH
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Pass-Through Statistic: REMOTE_SIZE
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: OFFHEAP_GET
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: OFFHEAP_PUT
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: OFFHEAP_REMOVE
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: DISK_GET
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: DISK_PUT
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: DISK_REMOVE
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: XA_COMMIT
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: XA_ROLLBACK
DEBUG net.sf.ehcache.statistics.extended.ExtendedStatisticsImpl Mocking Operation Statistic: XA_RECOVERY
DEBUG net.sf.ehcache.Cache Initialised cache: deviceCache
DEBUG net.sf.ehcache.config.ConfigurationHelper CacheDecoratorFactory not configured. Skipping for 'personCache'.
DEBUG net.sf.ehcache.config.ConfigurationHelper CacheDecoratorFactory not configured for defaultCache. Skipping for 'personCache'.
DEBUG com.googlecode.ehcache.annotations.impl.CacheAttributeSourceImpl Adding CACHE advised method 'detect' with attribute: CacheableAttributeImpl [cacheInstanceResolver=com.googlecode.ehcache.annotations.resolver.SingletonCacheableCacheResolver@7a1b0c08, cacheKeyGenerator=HashCodeCacheKeyGenerator [includeMethod=true, includeParameterTypes=true, useReflection=false, checkforCycles=false], parameterMask=ParameterMask [mask=[]]]
Apr 3, 2013 2:03:12 PM org.springframework.web.context.ContextLoader initWebApplicationContext
DEBUG com.mycompany.Controller trying to get resource'
DEBUG com.mycompany.PersonServiceImpl Missed 
DEBUG com.mycompany.Controller got person'
DEBUG com.mycompany.Controller trying to get resource'
DEBUG com.mycompany.PersonServiceImpl Missed 
DEBUG com.mycompany.Controller got person'

所以我的问题是,为什么它在我的单元测试中有效,而不是 webapp?我将如何使用 spring 注释而不是 googlecode 注释?

4

3 回答 3

10

您的PersonService服务未实现接口。Ehcache-spring-annotations 需要一个接口,如常见问题解答中所述:

要求 1:你的类必须实现一些(任何)接口。如果您的类没有实现接口,则该项目将无法创建代理来模仿您的类并在您的注释方法周围应用缓存语义。

于 2013-04-04T03:14:57.613 回答
3

即使我有一个接口,我在实现类上也有 @Cacheable 注释。一旦我将它移动到接口类,它就会被缓存。

于 2013-04-17T16:17:41.260 回答
0

您需要在 spring 上下文 xml 或 Spring 配置文件中启用 eh 缓存注释。例如

<ehcache:annotation-driven cache-manager="ehCacheManager" />
于 2014-11-27T14:24:01.407 回答