spring中使用cache

简述

使用内存等快速访问介质缓存热点数据,以此提高性能和增加吞吐量。
spring定义了CacheManager和Cache接口统一不同的缓存技术。其中CacheManager是Spring提供的各种缓存技术的抽象接口。而Cache接口包含缓存的各种操作,spring本身并没有提供缓存功能的实现(提供了list,map)。1
详见官方文档Cache Abstraction

注解

@EnableCaching

开启缓存

@Configuration
@EnableCaching
public class AppConfig {
}

Alternatively, for XML configuration you can use the cache:annotation-driven element:

<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"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/cache https://www.springframework.org/schema/cache/spring-cache.xsd">

        <cache:annotation-driven/>
</beans>

@Cacheable

触发缓存填充,即缓存中存在直接返回,否则执行具体实现获取数据并添加到缓存中。

  • value、cacheNames:两个等同的参数,用于指定缓存存储的集合名。
  • key:缓存对象的key值,非必需,缺省按照函数的所有参数组合作为key值,若自己配置需使用SpEL表达式,比如:@Cacheable(key = “#p0”):使用函数第一个参数作为缓存的key值
  • condition:缓存对象的条件,非必需,也需使用SpEL表达式,只有满足表达式条件的内容才会被缓存,比如:@Cacheable(key = “#p0”, condition = “#p0.length() < 3”),表示只有当第一个参数的长度小于3的时候才会被缓存
  • unless:另外一个缓存条件参数,非必需,需使用SpEL表达式。它不同于condition参数的地方在于它的判断时机,该条件是在函数被调用之后才做判断的,所以它可以通过对result进行判断。
  • keyGenerator:用于指定key生成器,非必需。若需要指定一个自定义的key生成器,我们需要去实现org.springframework.cache.interceptor.KeyGenerator接口,并使用该参数来指定。需要注意的是:该参数与key是互斥的
  • cacheManager:用于指定使用哪个缓存管理器,非必需。只有当有多个时才需要使用
  • cacheResolver:用于指定使用那个缓存解析器,非必需。需通过org.springframework.cache.interceptor.CacheResolver接口来实现自己的缓存解析器,并用该参数指定。

@CacheEvict

触发缓存移除

  • allEntries:非必需,默认为false。当为true时,会移除所有数据。如:@CachEvict(cacheNames=”test”,allEntries=true)
  • beforeInvocation:非必需,默认为false,会在调用方法之后移除数据。当为true时,会在调用方法之前移除数据。如方法有异常则不移除缓存。

@CachePut

触发缓存更新

@Caching

灵活组合如何触发缓存

@CacheConfig

在类级别共享缓存的配置

样例

controller

@RestController
@RequestMapping("/cache")
public class CacheTestController {

    @Autowired
    CacheTestService cacheTestService;

    @RequestMapping("get")
    public SimpleResp get(int id) {
        String value = cacheTestService.get(id);
        return new SimpleResp(true, value + "," + System.currentTimeMillis());
    }

    @RequestMapping("update")
    public SimpleResp update(int id, String value) {
        cacheTestService.update(id, value);
        return new SimpleResp(true, System.currentTimeMillis());
    }

    @RequestMapping("del")
    public SimpleResp del(int id) {
        cacheTestService.del(id);
        return new SimpleResp(true, System.currentTimeMillis());
    }

}
public class SimpleResp {

    private final boolean success;
    private final Object msg;

    public SimpleResp(boolean success) {
        this(success, "");
    }

    public SimpleResp(boolean success, Object msg) {
        this.success = success;
        this.msg= msg;
    }

    public boolean isSuccess() {
        return success;
    }

    public Object getMsg() {
        return msg;
    }
}

service

@Service
public class CacheTestService {

    static List<String> list = new ArrayList<>();

    static {
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
    }

    @Cacheable(cacheNames = "test", key = "#p0")
    public String get(int id) {
        System.out.println("load from local====" + id);
        return list.get(id);
    }

    @CachePut(cacheNames = "test", key = "#p0")
    public String update(int id, String value) {
        System.out.println("update local====" + id + "," + value);
        list.add(id, value);
        return value;
    }

    @CacheEvict(cacheNames = "test", key = "#p0")
    public void del(int id) {
        String value = get(id);
        System.out.println("del local====" + id + "," + value);
        list.remove(value);
    }

}

main

@SpringBootApplication
@EnableCaching
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }

}

application.yml

spring:
  cache:
    type: simple

测试

# 测试请求
~$ curl http://127.0.0.1:10010/cache/get?id=2
~$ curl http://127.0.0.1:10010/cache/update?id=2&value=test
~$ curl http://127.0.0.1:10010/cache/del?id=2
# 看控制台输出

注意

缓存失效

The default advice mode for processing caching annotations is proxy, which allows for interception of calls through the proxy only. Local calls within the same class cannot get intercepted that way. For a more advanced mode of interception, consider switching to aspectj mode in combination with compile-time or load-time weaving.

  • <cache:annotation-driven/>有一个mode属性,可选值有proxy和aspectj。默认是使用proxy。当mode为proxy时,只有缓存方法在外部被调用的时候cache才会发生作用,如果一个缓存方法在其声明对象内部被调用时cache是不会发生作用的。而mode为aspectj时就不会有这种问题。
  • 使用proxy时,只有public方法上的@Cacheable等标注才会起作用,如果需要非public方法上的方法也可以使用cache时把mode设置为aspectj。
  • <cache:annotation-driven/>还可以指定一个proxy-target-class属性,表示是否要代理class,默认为false。我们前面提到的@Cacheable@cacheEvict等也可以标注在接口上,这对于基于接口的代理来说是没有什么问题的,但是需要注意的是当我们设置proxy-target-class为true或者mode为aspectj时,是直接基于class进行操作的,定义在接口上的@Cacheable等Cache注解不会被识别到,那对应的cache也不会起作用了。

detail you can see from cache-annotation-enable

<cache:annotation-driven/> looks for @Cacheable/@CachePut/@CacheEvict/@Caching only on beans in the same application context in which it is defined. This means that, if you put <cache:annotation-driven/> in a WebApplicationContext for a DispatcherServlet, it checks for beans only in your controllers, not your services. See the MVC section for more information.

<cache:annotation-driven/>只会去寻找定义在同一个ApplicationContext下的@Cacheable等缓存注解。

整合2

ConcurrentMap

https://docs.spring.io/spring-framework/docs/current/reference/html/integration.html#cache-store-configuration-jdk

Ehcache-based Cache

https://docs.spring.io/spring-framework/docs/current/reference/html/integration.html#cache-store-configuration-ehcache
Ehcache

Caffeine Cache

https://docs.spring.io/spring-framework/docs/current/reference/html/integration.html#cache-store-configuration-caffeine

一个请求的生命周期里实现缓存

https://www.cnblogs.com/imyijie/p/11651679.html


  1. SpringBoot中Cache的正确使用 ↩︎

  2. Spring Boot Cache使用与整合 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值