SpringBoot与缓存

SpringBoot与缓存

JSR-107、Spring缓存抽象、整合redis

@EnableCaching

开启缓存
@Cacheable

在Spring Cache注解属性中(比如key,condition和unless),Spring的缓存抽象使用了SpEl表达式,从而提供了属性值的动态生成及足够的灵活性。

下面的代码根据用户的userCode进行缓存,对于key属性,使用了表达式自定义键的生成。

public class UserService {
    private Map<Integer, User> users = new HashMap<Integer, User>();
    {
        users.put(1, new User("1", "w1",37));
        users.put(2, new User("2", "w2", 34));
    }

    @Cacheable(value = "users", key = "#user.userCode" condition = "#user.age < 35")
    public User getUser(User user) {
        System.out.println("User with id " + user.getUserId() + " requested.");
        return users.get(Integer.valueOf(user.getUserId()));
    }
名称位置描述示例
methodNameroot对象当前被调用的方法名#root.methodname
methodroot对象当前被调用的方法#root.method.name
targetroot对象当前被调用的目标对象实例#root.target
targetClassroot对象当前被调用的方法的参数列表#root.args[0]
cachesroot对象当前方法调用使用的缓存列表#root.caches[0].name
Argument Name执行上下文当前被调用的方法的参数,如findArtisan(Artisan artisan),可以通过#artsian.id获得参数#artsian.id #id
result执行上下文方法执行后的返回值(仅当方法执行后的判断有效,如 unless cacheEvict的beforeInvocation=false)#result

原理

SpringBoot我们知道自动注入的时候都是XXXAutoConfiguration类的。所以我们寻找CacheAutoConfiguration

@Import({CacheAutoConfiguration.CacheConfigurationImportSelector.class})
public class CacheAutoConfiguration {
    public CacheAutoConfiguration() {
    }

可以看到导入了一个CacheConfigurationImportSelector类,
我们在这个类中最后返回的数据打断点看一下

static class CacheConfigurationImportSelector implements ImportSelector {
        CacheConfigurationImportSelector() {
        }

        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            CacheType[] types = CacheType.values();
            String[] imports = new String[types.length];

            for(int i = 0; i < types.length; ++i) {
                imports[i] = CacheConfigurations.getConfigurationClass(types[i]);
            }

            return imports;
        }
    }

总共有9个Configurations。默认使用的SimpleCacheConfiguration
在这里插入图片描述
通过在yml中设置debug=true,来查看调用逻辑,发现命中了
在这里插入图片描述
其他的均未命中
在这里插入图片描述
SimpleCacheConfiguration

 @Bean
    public ConcurrentMapCacheManager cacheManager() {
        ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
        List<String> cacheNames = this.cacheProperties.getCacheNames();
        if (!cacheNames.isEmpty()) {
            cacheManager.setCacheNames(cacheNames);
        }

        return (ConcurrentMapCacheManager)this.customizerInvoker.customize(cacheManager);
    }

运行流程

以@Cacheable为例
1、方法运行前先去查询Cache(缓存组件),按照cacheNames指定的名字去获取,
(CacheManager先获取相应的缓存),第一次会嗲用createConcurrentMapCache自动创建一个缓存。以hashmap的方式保存数据
2、去Cache中查找缓存的内容,使用一个Key,默认是方法的参数
key是按照某种策略生成的,默认使用KeyGenerator生成,默认使用SimpleKeyGenerator生成Key
SimpleKeyGenerator生成key的默认策略:

  • 如果没有参数:key=new Simplekey(),
  • 如果有一个参数:key=参数的值,
  • 如果有多个参数:key=new Simplekey(params)
    3、若没有查到缓存就调用目标方法,
    4、将目标方法返回的信息插入到缓存store中

所以就是在方法执行执行会检查一遍缓存,按照默认参数的值作为key,若没有就运行方法并且把结果放入缓存,
以后再来调用就可以直接使用缓存中的数据

核心:
1、使用CacheManager【ConcurrentMapCacheManager】按照名字得到cache【ConcurrentHashMap】组件,
2、key使用KeyGenerator生成的,默认SimpleKeyGenerator

@Cacheable属性

几个属性:
* cachenames/value:指定缓存组件的名字
* key:缓存数据使用的key:可以用它来指定,默认是使用方法参数的值:1、方法的返回值
* 编写SpEL:#id #root.args[0]
* keyGenerator:key的生成器,可以指定key的生成器的组件#id 【与key二选一】
* CacheManager:指定缓存管理器,或者cacheResolver指定获取解析器
* Condition:指定符合条件的情况才缓存【Condition=“#id>0”】
* unless:当unless指定的条件为true,那么方法的返回值就不会被缓存。可以获取到结果进行判断【unless=“#result==null”】
* sync:是否使用异步模式

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值