【问题标题】:Spring Cacheable vs CachePut?Spring Cacheable vs CachePut?
【发布时间】:2015-04-15 11:40:38
【问题描述】:
@CachePut or @Cacheable(value = "CustomerCache", key = "#id")
public Customer updateCustomer(Customer customer) {
   sysout("i am inside updateCustomer");
    ....
    return customer;
}

我在CachePut源代码下找到了以下文档

CachePut 注解不会导致目标方法被跳过—— 相反,它总是导致方法被调用,其结果是 放入缓存中。

这是否意味着如果我使用 @Cacheable , updateCustomer 方法将只执行一次,结果将在缓存中更新。后续调用 updateCustomer 不会执行 updateCustomer ,它只会更新缓存。

而在@CachePut 的情况下,updateCustomer 方法将在每次调用时执行,结果将在缓存中更新。

我的理解正确吗?

【问题讨论】:

  • 如果缓存阻止调用昂贵的函数超出需要,为什么使用 @CachePut 来 - 再次 - 使函数每次都被执行?

标签: java spring caching


【解决方案1】:

是的。

我什至做了一个测试来确定:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CacheableTest.CacheConfigurations.class)
public class CacheableTest {

    public static class Customer {

        final private String id;
        final private String name;

        public Customer(String id, String name) {
            this.id = id;
            this.name = name;
        }

        public String getId() {
            return id;
        }

        public String getName() {
            return name;
        }

    }

    final public static AtomicInteger cacheableCalled = new AtomicInteger(0);
    final public static AtomicInteger cachePutCalled = new AtomicInteger(0);

    public static class CustomerCachedService {


        @Cacheable("CustomerCache")
        public Customer cacheable(String v) {
            cacheableCalled.incrementAndGet();
            return new Customer(v, "Cacheable " + v);
        }

        @CachePut("CustomerCache")
        public Customer cachePut(String b) {
            cachePutCalled.incrementAndGet();
            return new Customer(b, "Cache put " + b);
        }

    }

    @Configuration
    @EnableCaching()
    public static class CacheConfigurations {

        @Bean
        public CustomerCachedService customerCachedService() {
            return new CustomerCachedService();
        }

        @Bean
        public CacheManager cacheManager() {
            return new GuavaCacheManager("CustomerCache");
        }

    }

    @Autowired
    public CustomerCachedService cachedService;

    @Test
    public void testCacheable() {
        for(int i = 0; i < 1000; i++) {
            cachedService.cacheable("A");
        }
        Assert.assertEquals(cacheableCalled.get(), 1);
    }

    @Test
    public void testCachePut() {
        for(int i = 0; i < 1000; i++) {
            cachedService.cachePut("B");
        }
        Assert.assertEquals(cachePutCalled.get(), 1000);
    }

}

【讨论】:

    【解决方案2】:

    @CachePut 总是让方法执行。如果您希望使用方法执行的结果更新缓存,则通常使用它。
    示例:当您要更新已缓存的陈旧数据时,而不是完全耗尽缓存。

    @Cacheable 对于给定的缓存键只会执行一次,后续请求不会执行该方法,直到缓存过期或被刷新。

    【讨论】:

    • 所以如果我用@CacheEvict 注释触发方法,那么在@Cachable 注释之后的方法将被执行?
    • @KamilW。 - 是的,它应该执行。
    • 如果每次都运行该方法,使用@CachePut 缓存数据有什么好处吗?
    • @Grez.Kev,如果你想清理缓存,你可以使用@CachePut,例如一个陈旧的数据在那里,你想重新缓存一些后端数据。
    【解决方案3】:

    是的,你完全正确。

    @Cacheput 和@Cacheable 结合使用。

    @Cacheable 不会在每次调用时更新缓存。为了删除陈旧数据,必须有一个使用@Cacheput 清除陈旧数据的服务。

    以下答案适用于使用番石榴缓存构建缓存的人。 使用番石榴缓存,应用的时间间隔将在一段时间后清空缓存,@Cacheput 不是这种情况。 @Cacheput 只会更新陈旧的值,因此它每次都会调用该方法来更新缓存。

    希望我的回答能解决你的问题。

    【讨论】:

    猜你喜欢
    • 2020-09-30
    • 1970-01-01
    • 2020-08-31
    • 2019-12-09
    • 1970-01-01
    • 2021-10-12
    • 1970-01-01
    • 2012-12-25
    • 1970-01-01
    相关资源
    最近更新 更多