当前位置: 首页 > 知识库问答 >
问题:

Spring3.1@Cacheable-方法仍在执行

谭俊
2023-03-14

我正在尝试实现Spring3.1缓存,正如这里和这里所解释的,但它似乎不起作用:我的方法每次都会运行,即使它被标记为@cacheable。我做错了什么?

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

Spring-test-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>

我的测试。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;
    }
}

相关Pom条目:(spring版本=3.1.1.发布)

    <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>

当我运行测试时,Spring会发出一些调试消息,这些消息看起来好像我的缓存已经初始化,没有错误

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的方法调用和每次打印来自someMethod内部的print语句之间不显示缓存检查。

有什么我遗漏的吗?

共有3个答案

米承嗣
2023-03-14

除了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;
    }
}
周意智
2023-03-14

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

匡晟
2023-03-14

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

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

方法可见性和@Cacheable/@CachePut/@cacheexecute

使用代理时,应仅将@Cache注释应用于具有公共可见性的方法。

  1. 您可以在同一目标对象中自调用someMethod
 类似资料:
  • 为什么spring对一个注释为@Cacheable的方法的一次调用执行我的定制@Cacheable密钥生成器两次,为什么不只执行一次。 我的KeyGenerator实现 我的方法用@Cacheable和自定义keyGenerator注释 spring Rest控制器,它调用用@cacheable注释的方法 当我用自定义的keyGenerator对用@Cacheable注释的方法进行一次调用时,我在

  • 当我从not bean类中的方法调用Cacheable方法时,我突然发现@Cacheable不起作用。 请在下面找到我的代码,并帮助我什么是问题或我错过的东西。

  • 我在Spring3.1中使用@Cacheable。我对Cacheable中的值和键映射参数有点混淆。以下是我正在做的: 这里发生的情况是,第二个方法依赖于第一个方法的选定值,但问题是假设当我传递zoneMastNo=1和areaMastNo=1时,第二个方法返回第一个方法结果。事实上,我有很多服务,因此,我希望使用公共值来缓存特定的用例。现在我的问题是: 我如何解决这个问题 对每个服务都使用cac

  • 我从Spring文档(https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/cache/annotation/Cacheable.html#condition--)中读到,可以使用SpEL指定方法参数的条件。 我一直在尝试同样的方法,但失败了。以下是我的方法: 这是我的POJO: 但

  • 我试图在一个方法上调用@CacheEvict和@Cacheable注释。 在调用@CacheEvict时,我想删除特定键的缓存数据,然后再次缓存方法响应的新鲜数据。但它没有缓存新鲜数据?。而且它也没有给出任何错误?。

  • 是否可以在同一方法上使用和?