2012-04-27 171 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

相關問題