使用函数接口实现一个简单的缓存处理器

正文
提到缓存的使用(应用层面),我们可能首先想到spring-cache,直接在需要加缓存的方法上加一个注解即可。但是简单的东西往往不是很灵活,并不能很好的适配一些特定场景。所以我打算用函数接口实现一个简单的本地缓存(caffeine)处理器。(spring-cache也有很多可选的缓存实现,但貌似想要清除缓存,需要触发缓存失效的注解,不是那么随心所欲)
思路很简单,定义一个cacheKey,在业务逻辑调用前根据cacheKey判断我需要的数据是否在缓存中,如果存在,直接从缓存中返回数据,如果不存在,就去调用业务逻辑,之后把执行结果放入缓存中,从而避免了数据库的交互和多余的运算。(主要就是通过减少IO来提升性能)
代码
package cn.mrxionge.idemo.cache;

/**
 * 缓存处理接口
 *
 * @author MrXionGe
 * @since 2020/11/5
 */
@FunctionalInterface
public interface LocalCacheHandler<T> {

    /**
     * 自定义逻辑
     *
     * @return 自定义的执行结果
     */
    T invoke();
}

↑↑↑ 这里我们创建一个函数接口,后续的具体业务逻辑写在接口的实现中。
package cn.mrxionge.idemo.cache;

import com.github.benmanes.caffeine.cache.Cache;
import lombok.extern.slf4j.Slf4j;

/**
 * 本地缓存工具
 *
 * @author MrXionGe
 * @since 2020/11/5
 */
@Slf4j
@SuppressWarnings("all")
public class LocalCacheUtil {

    /**
     * 执行需要被缓存的自定义逻辑或方法<br>
     * 并在逻辑的前后自动增加缓存操作
     *
     * @param <T>          执行结果返回值类型
     * @param cache        caffeine缓存对象
     * @param cacheKey     key
     * @param cacheHandler 缓存处理器(处理需要被缓存的逻辑)
     * @return 自定义的执行结果
     */
    public static <T> T cache(Cache<String, Object> cache, String cacheKey, LocalCacheHandler<T> cacheHandler) {
        log.debug("LocalCache --> cacheKey: {}", cacheKey);
        Object obj = cache.getIfPresent(cacheKey);
        if (obj != null) {
            log.debug("LocalCache --> cache hit");
            return (T) obj;
        }
        log.debug("LocalCache --> cache miss");
        T result = cacheHandler.invoke();
        log.debug("LocalCache --> add into cache");
        cache.put(cacheKey, result);
        return result;
    }
}

↑↑↑ 这里创建一个缓存工具,给出一个静态方法。cache方法中,在调用接口实现之前,我们根据cacheKey判断我们需要的数据是否在缓存中,在调用接口实现之后,把执行结果放到缓存中。
package cn.mrxionge.idemo;

import cn.hutool.core.thread.ThreadUtil;
import cn.mrxionge.idemo.cache.LocalCacheUtil;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * @author MrXionGe
 * @since 2020/11/5
 */
@Slf4j
public class CacheTest {

    public static void main(String[] args) {
        //创建缓存对象
        Cache<String, Object> cache = Caffeine.newBuilder().maximumSize(100).expireAfterAccess(10, TimeUnit.SECONDS).build();
        //自定义参数
        int a = 111;
        int b = 222;
        for (int i = 0; i < 2; i++) {
            Integer result = LocalCacheUtil.cache(cache, "key_" + a + b, () -> {
                /*---------- 复杂业务逻辑 ----------*/
                log.debug("假装执行复杂运算...");
                ThreadUtil.sleep(1000);
                log.debug("终于执行完了.......");
                return a + b;
                /*---------- 复杂业务逻辑 ----------*/
            });
            log.info("方法执行结果: " + result);
        }
        //清理缓存 非必要
        cache.invalidateAll();
    }
}

↑↑↑ 写一个简单的测试类,这里创建了一个方法级的缓存对象。(当然也可以选择全局的缓存对象,视情况而定)我们直接调用缓存工具中的方法,并且传入缓存相关的参数,剩下的就是写业务逻辑了。这里通过sleep方法假装这个逻辑需要运行1秒才会有结果。运行之后我们可以通过日志查看执行顺序和结果。

在这里插入图片描述

或者查看日志前的时间,也可以看出缓存的效果。
我这里只是给出了一个很简单的demo,但是这个思路可以发散下去。
思路和AOP的before、after是一样的,不仅仅可以应用在上面的本地缓存上。我们把本地缓存替换成redis也行,或者用它实现简单的分布式锁也OK,环绕日志、性能分析……等等。。。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值