当前位置: 首页 > 工具软件 > CacheManager > 使用案例 >

SpringCache的CacheManager接口和Cache接口

沈弘文
2023-12-01

总结

  1. SpringCache定义了@Cacheable、@CachePut、@CacheEvict三个注解,分别对应查询、更新、删除时对缓存的处理
  2. 只需要在Server类添加该注解,就可以通过AOP自动代理实现缓存查询、缓存更新、缓存删除,使用形式如下,@Cacheable、@CachePut会在unless条件成立时将返回值添加进缓存,而@Cacheable在有缓存时不会执行Server类方法。@CacheEvict会直接删除缓存名为value的缓存中的键值对的键为key的键值对
 @Override
 @Cacheable(value = "userCache", key = "#id", unless = "#result == null")
 public User getUserById(Long id) {
     System.out.println("运行");
     return userMapper.selectById(id);
 }

 @Override
 @CachePut(value = "userCache", key = "#user.id", unless = "#result == null")
 public User updateUser(User user) {
     userMapper.updateById(user);
     return userMapper.selectById(user.getId());
 }

 @Override
 @CacheEvict(value = "userCache", key = "#id")
 public void deleteUserById(Long id) {
     userMapper.deleteById(id);
 }
  1. 缓存的name为userCache,也就是下面接口方法对应的缓存名字,key就是通过name获取后,该缓存类似Map结构,可以根据key存储值和取出值,@Cacheable也是根据每次需要执行的代码key是否在缓存中存在来决定是否执行,存在则不执行

  2. 而SpringCache通过注解实现缓存实际上的逻辑是在CacheManager和Cache中定义的,在CacheManager使用缓存名字value,获取缓存Cache,然后缓存Cache中定义了对键值对增删查改的方法,通过这种接口抽象,可以自定义缓存,也可以整合第三方缓存,如本地缓存Caffeine和分布式缓存Redisson

  3. 整合本地缓存Caffeine和分布式缓存Redisson,只需使用注解@EnableCaching,这是SpringCache的注解,在该注解下的类注册一个CacheManager即整合成功

@Configuration
@EnableCaching
public class CaffeineConfig {
    @Bean
    public Caffeine caffeineConfig() {
        return
                Caffeine.newBuilder()
                        .maximumSize(10000).
                        expireAfterWrite(60, TimeUnit.MINUTES);
    }
    @Bean
    public CacheManager cacheManager(Caffeine caffeine) {
        CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
        caffeineCacheManager.setCaffeine(caffeine);
        return caffeineCacheManager;
    }
}
@Configuration
@EnableCaching
public class RedissonConfig {
    @Bean(destroyMethod = "shutdown")
    public RedissonClient Redisson() {
        Config config = new Config();
        config.useSingleServer()
                .setAddress("redis://127.0.0.1:6379");
        return Redisson.create(config);
    }
    @Bean
    CacheManager cacheManager(RedissonClient RedissonClient) {
        Map<String, CacheConfig> config = new HashMap<String, CacheConfig>();
        config.put("UserCache",
                new CacheConfig(
                        24 * 60 * 1000,
                        12 * 60 * 1000));
        return new RedissonSpringCacheManager(RedissonClient, config);
    }
}

CacheManager接口方法

方法名作用
Cache getCache(String name)获取与给定名称关联的缓存
Collection< String> getCacheNames()获取此管理器已知的缓存名称的集合

Cache接口方法

方法名作用
String getName()返回缓存的名称,也就是缓存关联的名称
Object getNativeCache()返回基础缓存提供程序
ValueWrapper get(Object key)在该缓存中查找该键key对应的值。如果缓存不包含该键的映射,则直接返回null,否则,缓存的值将在ValueWrapper中返回,ValueWrapper内只有一个get()方法用于获取值,这样设计的原因是表示存在该缓存,但其值为空
T get(Object key, Class type)返回此缓存将指定键key映射到的值,并将其转换为类Class的对象
T get(Object key, Callable valueLoader)返回此缓存将指定键key映射到的值,必要时从Callable类调用方法获取该值,这个必要时完全取决于自己实现,可以将在该缓存不存在时调用Callable的call方法获取一个值并返回
void put(Object key, Object value)将指定的值value与此缓存中的指定键key相关联。如果缓存以前包含此键的映射,则旧值将替换为指定值
void evict(Object key)如果存在此键key的映射,则从缓存中删除该键值对
void clear()清空缓存中所有映射,即清空所有键值对

自定义SpringCache

MyCacheConfig.java
配置类

@Configuration
@EnableCaching
public class MyCacheConfig {

    @Bean
    CacheManager cacheManager() {
        return new MyCacheManager();
    }
}

MyCacheManager.java
缓存管理器类,实现CacheManager接口

public class MyCacheManager implements CacheManager {
    private Map<String, Cache> map = new HashMap<>();

    @Nullable
    @Override
    public Cache getCache(String name) {
        Cache cache = map.get(name);
        if (cache == null) {
            cache = new MyCache(name);
            map.put(name, cache);
        }
        return cache;
    }

    @Override
    public Collection<String> getCacheNames() {
        return map.keySet();
    }
}

MyCache.java
缓存类,实现Cache接口

public class MyCache implements Cache {
    private String name;
    private Map<Object, ValueWrapper> map = new HashMap<>();

    public MyCache(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public Object getNativeCache() {
        return map;
    }

    @Nullable
    @Override
    public ValueWrapper get(Object key) {
        return map.get(key);
    }

    @Nullable
    @Override
    public <T> T get(Object key, @Nullable Class<T> type) {
        ValueWrapper valueWrapper = map.get(key);
        if (valueWrapper != null) {
            return (T) valueWrapper.get();
        }
        return null;
    }

    @Nullable
    @Override
    public <T> T get(Object key, Callable<T> valueLoader) {
        ValueWrapper valueWrapper = map.get(key);
        if (valueWrapper != null) {
            return (T) valueWrapper.get();
        }
        T call = null;
        try {
            call = valueLoader.call();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return call;
    }

    @Override
    public void put(Object key, @Nullable Object value) {
        map.put(key, new ValueWrapper() {
            private Object v = value;
            @Nullable
            @Override
            public Object get() {
                return v;
            }
        });
    }

    @Override
    public void evict(Object key) {
        map.remove(key);
    }

    @Override
    public void clear() {
        map.clear();
    }
}
 类似资料: