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

Spring Boot启动缓存和可缓存注释不工作

端木震博
2023-03-14

我想将主数据缓存到Redis。

所以,我写了这些代码。

@Configuration
@EnableCaching
public class AppConfig extends CachingConfigurerSupport {
    @Bean
    @Autowired
    public CacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        Map<String, Long> expires = new HashMap<>();
        expires.put("cache.day", new Long(24 * 60 * 60));
        cacheManager.setExpires(expires);
        return cacheManager;
    }
}

package com.taisho.artifacts.repository.impl;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;

@Repository
public class TestRepository {

    @Cacheable(value = "cache.day", key = "'cache.test'")
    public List<String> getTest() {
        List<String> list = new ArrayList<>();
        list.add("test");
        list.add("sample");
        return list;
    }

    public void printTest() {
        System.out.println(getTest());
    }
}

和ymlfile

spring:
  redis:
    host: 127.0.0.1
    port: 26379

但是,缓存不工作...

无论何时调用printTest方法,都将执行“getTest”方法。Redis没有数据。。。我的代码中有什么问题?

SpringBoot版本是1.4.0

依赖关系是

compile("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
compile("org.springframework.boot:spring-boot-starter-data-redis:${springBootVersion}")
compile("org.springframework.boot:spring-boot-autoconfigure:${springBootVersion}")

共有1个答案

白子明
2023-03-14

Spring AOP是基于代理的,所以当你从printTest()方法调用getTest()方法时,getTest()方法将在this引用上调用,而不是能够执行缓存操作。通常这是一个设计气味,你最好重新考虑你现在的设计。但是作为一种解决方案,您可以使用AopContext

public void printTest() {
    System.out.println(((TestRepository) AopContext.currentProxy()).getTest());
}

假设您有一个客户端代码,可以通过依赖项注入访问TestRepository

@Component
class SomeUnfortunateClient {
    // I know field injection is evil!
    @Autowired TestRepository testRepository;

    void youAreGoingToBeSurprised() {
        testRepository.printTest();
    }
}

TestRepository是一个Spring管理的存储库,为了向TestRepository添加附加功能,例如:缓存,Spring将为其创建一个代理。这意味着对testRepository对象引用的方法调用将是对代理的调用,因此代理将能够委托给与该特定方法调用相关的所有拦截器(建议)。在您的情况下,这些建议将检查缓存项是否存在。

然而,一旦调用最终到达目标对象,TestRepository引用在这种情况下,它可能对自己进行的任何方法调用,如System.out.println(getTest());,都将被调用针对this引用,而不是代理。这意味着自调用不会导致与方法调用相关的建议有机会执行。

正如Spring文档所述:

好吧,那么对此该怎么办?最好的方法是重构代码,使自调用不会发生。当然,这确实需要你做一些工作,但这是最好的、侵入性最小的方法。下一个方法绝对是可怕的,我几乎不愿指出,正是因为它太可怕了。你可以(呛!)通过这样做,将类中的逻辑与Spring AOP完全联系起来:

public class SimplePojo implements Pojo {

    public void foo() {
        // this works, but... gah!
        ((Pojo) AopContext.currentProxy()).bar();
    }

    public void bar() {
        // some logic...
    }
}

这会将您的代码完全耦合到Spring AOP,并使类本身意识到它正在AOP上下文中使用的事实,这与AOP背道而驰。在创建代理时,还需要一些额外的配置。

这个答案在很大程度上基于Spring文档,所以对于(甚至!)更详细的讨论,您一定要查看Spring文档中的了解AOP代理部分。

 类似资料:
  • 我正在寻找集成Hazelcast到我的应用程序... 我的要求是将所有数据加载到缓存并从缓存中提取。。 我有两个选择。 1) Hazelcast IMap 2)因为我使用的是Spring启动,所以我可以使用(@Cacheable/@CacheEvict)。 我能得到一些建议吗... 提前谢谢你。。

  • 我的Spring应用程序由两个上下文xml配置文件组成,第一个是根上下文。xml仅扫描非控制器带注释的bean: 而第二个servlet上下文。xml包含所有spring mvc设置和扫描控制器带注释的bean web.xml上的DispatcherServlet配置如下所示 我想尝试基于注释的缓存,所以我将以下bean定义添加到root-context.xml 并使用一个带有注释的类来测试这一点

  • 本文向大家介绍CodeIgniter启用缓存和清除缓存的方法,包括了CodeIgniter启用缓存和清除缓存的方法的使用技巧和注意事项,需要的朋友参考一下 Codeigniter支持缓存技术,以达到最快的速度。尽管CI已经相当高效了,但是网页中的动态内容、主机的内存CPU和数据库读取速度等因素直接影响了网页的加载速度。依靠网页缓存,你的网页可以达到近乎静态网页的加载速度,因为他们将程序输出的结果保

  • 我正在使用注释来缓存我的方法的结果。出于性能原因,我想缓存从方法返回的和非null值。 但是这里的问题是Spring缓存非空值,但由于某种原因没有缓存空值。 这是我的密码: 我什么都试过了。就连我 但这也没什么帮助。有关于这个的指示吗?

  • 问题内容: 我想在Redis中实现绝对缓存和滑动缓存。没有人有任何资源链接,这将是有帮助的 问题答案: Redis已经为此提供了许多命令: 到期:设置密钥超时。 期望值:与以前相同,但是需要一个绝对的Unix时间戳(自1970年1月1日以来的秒数)。 TTL:返回具有超时功能的键的剩余生存时间 您必须了解有关Redis过期的重要一件事:仅当使用SET或GETSET移除或覆盖键时,才会清除超时值。所