spring redis 手动刷新缓存功能

spring redis 手动刷新缓存功能

背景

当我们在使用redis作为后台数据库缓存时,通常会有一套比较完善的更新策略,比如:按照某个固定时间过期。但是,在某些特定情况下(意料之外),后台数据已经更新,缓存中的数据需要手动同步。

思路

提取出刷新redis缓存的方法,注册在容器中。在需要的时候调用已注册的刷新方法,更新redis缓存。

实现

1. 注解

被注解的方法为刷新Redis的方法:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface RefreshCache {
    String value() default "";
}

2. 容器

存储所有刷新缓存的方法:

@Data
@Slf4j
public class CacheInvoker {

    private static List<CacheInvoker> invokers = new ArrayList<>();

    private Object targetObj;
    private Method targetMethod;

    public CacheInvoker(Object targetObj, Method targetMethod) {
        this.targetObj = targetObj;
        this.targetMethod = targetMethod;
    }

    public static void addInvoker(CacheInvoker cacheInvoker) {
        invokers.add(cacheInvoker);
    }

    public static void addInvokers(List<CacheInvoker> otherInvokers) {
        invokers.addAll(otherInvokers);
    }

    public void doInvoke() {
        Method method = getTargetMethod();
        Object target = getTargetObj();
        log.info("执行方法:{}", method.toString());
        ReflectionUtils.makeAccessible(method);
        ReflectionUtils.invokeMethod(method, target);
    }

    public static void doInvokes() {
        log.info("共{}个,初始化方法", invokers.size());
        invokers.forEach(CacheInvoker::doInvoke);
    }
}

3. spring bean 后处理器

将所有被RefreshCache注解的方法,存入CacheInvoker容器中

@Component
public class RefreshCacheBeanProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class<?> clazz = bean.getClass();
        Method[] methods = clazz.getDeclaredMethods();
        List<CacheInvoker> invokers = Stream.of(methods)
                .filter(method -> method.isAnnotationPresent(RefreshCache.class))
                .map(method -> {
                    CacheInvoker invoker = new CacheInvoker(bean, method);
                    invoker.doInvoke();
                    return invoker;
                })
                .collect(Collectors.toList());
        CacheInvoker.addInvokers(invokers);
        return bean;
    }
}

使用实例:

@Slf4j
@Service
public class RedisService {

    @RefreshCache
    public void initCache() {
        log.info("初始化redis 缓存");
    }
}

说明

  1. @RefreshCache注解,只有在spring 管理的实例中才生效,既类上有@Component注解。

代码仓库

https://gitee.com/thanksm/redis_learn/tree/master/refresh

你可能感兴趣的:(redis)