[笔记] Java Cache

依赖

                <dependency>
                        <groupId>com.github.ben-manes.caffeine</groupId>
                        <artifactId>caffeine</artifactId>
                </dependency>

                <dependency>
                        <groupId>com.github.ben-manes.caffeine</groupId>
                        <artifactId>jcache</artifactId>
                </dependency>

里面包含了

        <dependency>
            <groupId>javax.cache</groupId>
            <artifactId>cache-api</artifactId>
        </dependency>

如果只指定 cache-api 这个依赖,编译不会报错,但运行报错,因为这个只定义接口没有实现

也可以使用其他实现

定义要缓存的类,必须是可序列化的

package com.example.demo.entity;

import com.example.demo.utils.Logger;

import java.io.Serializable;


public class MyObject implements Serializable {
    private final String name;
    private final String id;

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

    public void display() {
        Logger.message("This is " + name + " id is " + id);
    }
}

定义 Factory,通过 @Bean 注解创建一个 Cache,这个 Cache 的 key 是 String,对应 value 是 MyObject

setExpiryPolicyFactory 决定了缓存失效时间

setCacheLoaderFactory 决定了如果 key 在缓存里不存在或失效的话,要怎么去获取

package com.example.demo.factory;

import com.example.demo.entity.MyObject;
import com.example.demo.utils.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.cache.Cache;
import javax.cache.Caching;
import javax.cache.configuration.Configuration;
import javax.cache.configuration.FactoryBuilder;
import javax.cache.configuration.MutableConfiguration;
import javax.cache.expiry.CreatedExpiryPolicy;
import javax.cache.expiry.Duration;
import javax.cache.spi.CachingProvider;

import java.util.concurrent.TimeUnit;

import static org.springframework.web.context.WebApplicationContext.SCOPE_APPLICATION;


@Component
public class MyCacheFactory {
    CachingProvider cachingProvider = Caching.getCachingProvider();

    @Bean
    @Scope(SCOPE_APPLICATION)
    public Cache<String, MyObject> produce() {
        Logger.message("MyCacheFactory produce conn");

        Configuration<String, MyObject> config =
                new MutableConfiguration<String, MyObject>()
                        .setTypes(String.class, MyObject.class)
                        .setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(TimeUnit.HOURS, 1)))
                        .setReadThrough(true)
                        .setCacheLoaderFactory(FactoryBuilder.factoryOf(MyObjectLoader.class));

        return cachingProvider.getCacheManager().createCache("MyObject", config);
    }
}

定义 MyObjectLoader 决定如果缓存不存在或过期,如何获取

package com.example.demo.factory;

import com.example.demo.entity.MyObject;
import com.example.demo.utils.Logger;

import javax.cache.integration.CacheLoader;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class MyObjectLoader implements CacheLoader<String, MyObject> {

    @Override
    public MyObject load(String key) {
        Logger.message("load " + key);
        return this.get(key);
    }

    @Override
    public Map<String, MyObject> loadAll(Iterable<? extends String> keys) {
        Logger.message("loadAll " + keys);

        Map<String, MyObject> mapper = new HashMap<>();

        for (String key : keys) {
            mapper.put(key, get(key));
        }

        return mapper;
    }

    private MyObject get(String key) {
        return new MyObject(key, UUID.randomUUID().toString());
    }
}

应用,@Autowired 自动找到了 @Bean 注解的返回类型为 Cache<String, MyObject> 的函数所创建的实例

    @Autowired
    private Cache<String, MyObject> cache;

    @PostConstruct
    public void init() {
        this.verifyCache();    // 第一次,缓存里找不到,会调用 load 和 loadAll
        Logger.message("\nbetween 2 verify cache");
        this.verifyCache();    // 第二次,缓存里找得到,直接返回缓存
    }

    public void verifyCache() {
        Logger.message("\n================\nverifyCache\n================\n");

        cache.get("a").display();
        cache.get("b").display();

        Set<String> set = new HashSet<>();
        set.add("c");
        set.add("d");
        Map<String, MyObject> mapper = cache.getAll(set);
        for (Map.Entry<String, MyObject> entry : mapper.entrySet()) {
           entry.getValue().display();
        }
    }

结果

================
verifyCache
================

load a
This is a id is 0cde6a55-04e9-498d-bcc6-7ff01c18ffe8
load b
This is b id is 89e86e9b-dbe0-4140-a0a8-449344fbba5d
loadAll [c, d]
This is c id is 42c101a8-40d6-4998-8905-758febf2841f
This is d id is 970e537e-9e5d-4c01-9226-e0261e1d0747

between 2 verify cache

================
verifyCache
================

This is a id is 0cde6a55-04e9-498d-bcc6-7ff01c18ffe8
This is b id is 89e86e9b-dbe0-4140-a0a8-449344fbba5d
This is c id is 42c101a8-40d6-4998-8905-758febf2841f
This is d id is 970e537e-9e5d-4c01-9226-e0261e1d0747
posted @ 2022-01-15 00:25  moon~light  阅读(173)  评论(0编辑  收藏  举报