2012-04-27 156 views
25

我试图按照解释的herehere来实现Spring 3.1缓存,但它似乎并不奏效:我的方法每次都会运行,即使它被标记为@cacheable 。我究竟做错了什么?Spring 3.1 @Cacheable - 仍然执行的方法

我已经将它与自己的配置文件一起移动到junit测试用例中,以将它与其他应用程序隔离开,但问题仍然存在。以下是相关文件:

弹簧试验servlet.xml中

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:cache="http://www.springframework.org/schema/cache" 
    xmlns:p="http://www.springframework.org/schema/p" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> 
<cache:annotation-driven /> 

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcache"/> 
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" 
     p:config-location="classpath:ehcache.xml"/> 
</beans> 

ehcache.xml中

<ehcache> 
<diskStore path="java.io.tmpdir"/> 
<cache name="cache" 
     maxElementsInMemory="100" 
     eternal="false" 
     timeToIdleSeconds="120" 
     timeToLiveSeconds="120" 
     overflowToDisk="true" 
     maxElementsOnDisk="10000000" 
     diskPersistent="false" 
     diskExpiryThreadIntervalSeconds="120" 
     memoryStoreEvictionPolicy="LRU"/> 

</ehcache> 

MyTest.java

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({"classpath:spring-test-servlet.xml"}) 
@Component 
public class MyTest extends TestCase { 

    @Test 
    public void testCache1(){ 
     for(int i = 0; i < 5; i++){ 
      System.out.println("Calling someMethod..."); 
      System.out.println(someMethod(0)); 
     } 
    } 

    @Cacheable("testmethod") 
    private int someMethod(int val){ 
     System.out.println("Not from cache"); 
     return 5; 
    } 
} 

相关双龙项:(春-version = 3.1.1.RELEASE)

<dependency> 
     <groupId>net.sf.ehcache</groupId> 
     <artifactId>ehcache-core</artifactId> 
     <version>2.5.1</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-context-support</artifactId> 
     <version>${spring.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-context</artifactId> 
     <version>${spring.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-core</artifactId> 
     <version>${spring.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-test</artifactId> 
     <version>${spring.version}</version> 
    </dependency> 

当我运行测试,春天推出,看起来像我的缓存是没有错误

DEBUG: config.ConfigurationHelper - No CacheManagerEventListenerFactory class specified. Skipping... 
DEBUG: ehcache.Cache - No BootstrapCacheLoaderFactory class specified. Skipping... 
DEBUG: ehcache.Cache - CacheWriter factory not configured. Skipping... 
DEBUG: config.ConfigurationHelper - No CacheExceptionHandlerFactory class specified. Skipping... 
DEBUG: store.MemoryStore - Initialized net.sf.ehcache.store.MemoryStore for cache 
DEBUG: disk.DiskStorageFactory - Failed to delete file cache.data 
DEBUG: disk.DiskStorageFactory - Failed to delete file cache.index 
DEBUG: disk.DiskStorageFactory - Matching data file missing (or empty) for index file. Deleting index file /var/folders/qg/xwdvsg6x3mx_z_rcfvq7lc0m0000gn/T/cache.index 
DEBUG: disk.DiskStorageFactory - Failed to delete file cache.index 
DEBUG: ehcache.Cache - Initialised cache: cache 
DEBUG: config.ConfigurationHelper - CacheDecoratorFactory not configured. Skipping for 'cache'. 
DEBUG: config.ConfigurationHelper - CacheDecoratorFactory not configured for defaultCache. Skipping for 'cache'. 

初始化,但调试输出显示没有缓存检查之间的方法调用的someMethod和print语句一些调试消息每次在someMethod中打印。

有什么我失踪了吗?

回答

76

http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/cache.html

在代理模式(这是默认值),只有外部方法调用 进来通过代理被截获。这意味着, 自我调用,实际上,一个目标对象调用 目标对象的另一种方法中的方法,不会导致实际 缓存在运行时即使被调用的方法被标记 @可缓存 - 考虑在这种情况下使用aspectj模式。

方法的知名度和@Cacheable/@CachePut/@CacheEvict

当使用代理服务器,你应该应用@Cache注释只 方法与公共知名度

  1. 您在同一个目标对象的自我调用someMethod
  2. 您的@Cacheable方法不公开。
+0

除了这个方法的问题,您需要提取到一个接口,所以Spring可以动态地为你的类写封装。 – RockMeetHardplace 2012-05-10 01:01:00

2

您需要定义一个与您在注释中引用的名称(“testmethod”)相匹配的名称的缓存。在ehcache.xml中为该缓存创建一个条目。

+0

这也是我原来的代码,这显然有一次我打电话的方式,试图把它的缓存(见接受的解决方案) – 2012-04-27 21:49:31

1

除了Lee Chee Kiam:这里是我的小项目解决方案,只有边缘使用旁路(未注释)的方法调用。 DAO简单地作为代理注入自己,并使用该代理调用它自己的方法,而不是简单的方法调用。所以@Cacheable被认为没有做复杂的手段。

强烈建议在代码文档,因为它可能看起来很奇怪的同事。但它易于测试,操作简单,快速实现,并为我提供了完整的AspectJ仪器。但是,对于更重的用法,我还会建议AspectJ解决方案,就像Lee Chee Kiam所做的那样。

@Service 
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) 
class PersonDao { 

    private final PersonDao _personDao; 

    @Autowired 
    public PersonDao(PersonDao personDao) { 
     _personDao = personDao; 
    } 

    @Cacheable(value = "defaultCache", key = "#id") 
    public Person findPerson(int id) { 
     return getSession().getPerson(id); 
    } 

    public List<Person> findPersons(int[] ids) { 
     List<Person> list = new ArrayList<Person>(); 
     for (int id : ids) { 
      list.add(_personDao.findPerson(id)); 
     } 
     return list; 
    } 
} 
+0

它是绕过代理模式的@Scope注释吗?我有一个类似的问题在这里http://stackoverflow.com/questions/36486620/correct-key-annotation-for-caching-on-items-in-a-list-rather-then-the-whole-list – 2016-04-07 20:47:02

+0

我'对不起,我想我没有把问题说得对。我没有看到与你的帖子的连接。 – 2016-04-08 20:06:23

+0

在这种情况下,“绕过”意味着该方法没有使用@Cachable进行注释,但是它在内部使用注入代理的chached方法,而WHICH又是“this”itslef的代理。有点怪异;)该对象被注入自身作为代理来避免复杂的instamentation。 – 2016-04-08 20:12:46

相关问题