NutzCN Logo
问答 interface UpdateStrategy 对象初始化问题
发布于 1723天前 作者 Hamming 1342 次浏览 复制 上一个帖子 下一个帖子
标签:
package org.nutz.boot.starter.caffeine;

public interface UpdateStrategy {

    /**
     * 是否需要强制更新缓存
     * @param key 缓存键
     * @return should update ?
     */
    boolean shouldUpdate(String key);

    /**
     * 清除全部缓存
     * @param key
     * @return
     */
    boolean invalidateAll(String key);
}

package org.nutz.boot.starter.caffeine;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.nutz.aop.InterceptorChain;
import org.nutz.aop.MethodInterceptor;
import org.nutz.ioc.Ioc;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.log.Log;
import org.nutz.log.Logs;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;

@IocBean(create = "init")
public class CaffeineInterceptor implements MethodInterceptor {

    private static Log log = Logs.get();
    private static final ConcurrentMap<CacheStrategy, Cache<String, Object>> cacheMap = new ConcurrentHashMap<>();
    private static final Map<String, CacheStrategy> cacheStrategyMap = new HashMap<>();

    @Inject
    protected PropertiesProxy conf;

    protected KeyStringifier stringifier;

    protected UpdateStrategy updateStrategy;

    @Inject("refer:$ioc")
    protected Ioc ioc;

    private static Cache<String, Object> getCache(CacheStrategy strategy) {
        Cache<String, Object> cache = cacheMap.get(strategy);
        if (cache == null) {
            synchronized (strategy) {
                cache = cacheMap.get(strategy);
                if (cache == null) {
                    Caffeine<Object, Object> caffeine = Caffeine.newBuilder();
                    if (strategy.getMaxIdle() > 0) {
                        caffeine.expireAfterAccess(strategy.getMaxIdle(), TimeUnit.MILLISECONDS);
                    }
                    if (strategy.getMaxLive() > 0) {
                        caffeine.expireAfterWrite(strategy.getMaxLive(), TimeUnit.MILLISECONDS);
                    }
                    if (strategy.getMaxSize() > 0) {
                        caffeine.maximumSize(strategy.getMaxSize());
                    }
                    cache = caffeine.build();
                    cacheMap.put(strategy, cache);
                }
            }
        }
        return cache;
    }

    /**
     * 过滤器 实现缓存
     * @param chain
     * @throws Throwable
     */
    @Override
    public void filter(InterceptorChain chain) throws Throwable {
        Method method = chain.getCallingMethod();
        if (method.getReturnType() == void.class) {
            log.warnf("method [%s] is void,should not use @Cache", method);
            chain.doChain();
            return;
        }
        String name = method.getAnnotation(org.nutz.boot.starter.caffeine.Cache.class).value();
        CacheStrategy strategy = cacheStrategyMap.get(name);
        if (strategy == null) {
            log.warnf("CacheStrategy[%s] on Method[%s] doesn't exist", name, method);
            chain.doChain();
            return;
        }
        Cache<String, Object> cache = getCache(strategy);
        String key = getKey(method, chain.getArgs());
        Object value = cache.getIfPresent(key);
        if (value == null
//                || updateStrategy.invalidateAll(key)
                || updateStrategy.shouldUpdate(key)
                ) {
            chain.doChain();
//            if(updateStrategy.invalidateAll(key)){
//                cache.invalidateAll();
//            }
            cache.put(key, chain.getReturn());
        } else {
            chain.setReturnValue(value);
        }
    }

    /**
     * 获取执行方法名称
     * @param method
     * @param args
     * @return
     */
    private String getKey(Method method, Object[] args) {
        String fullName = String.format("%s.%s", method.getDeclaringClass().getName(), method.getName());
        if (args == null || args.length == 0) {
            return fullName;
        }
        return fullName + ":" + Arrays.stream(args).map(stringifier::stringify).collect(Collectors.joining("$"));
    }

    /**
     * 初始化
     */
    public void init() {
        String[] stringifierNames = ioc.getNamesByType(KeyStringifier.class);
        this.stringifier = Lang.isEmptyArray(stringifierNames) ? String::valueOf : ioc.get(KeyStringifier.class, stringifierNames[0]);
        log.debugf("use %s as KeyStringifier", this.stringifier);
        String[] updateStrategyNames = ioc.getNamesByType(UpdateStrategy.class);
        this.updateStrategy = Lang.isEmptyArray(updateStrategyNames) ? k -> false : ioc.get(UpdateStrategy.class, updateStrategyNames[0]);
        log.debugf("use %s as UpdateStrategy", this.updateStrategy);
        Map<String, CacheStrategy> map = new HashMap<>();
        conf.entrySet().stream().filter(entry -> entry.getKey().startsWith(CaffeineStarter.PRE)).forEach(entry -> {
            if (entry.getValue() == null) {
                return;
            }
            String[] split = entry.getKey().substring(CaffeineStarter.PRE.length()).split("\\.");
            if (split.length == 2) {
                // cache.name=10000,-1,-1 这种
                try {
                    String[] values = entry.getValue().replace(" ", ",").split(",");
                    long maxSize = Long.parseLong(values[0].trim());
                    long maxIdle = values.length > 1 ? Long.parseLong(values[1].trim()) : 0L;
                    long maxLive = values.length > 2 ? Long.parseLong(values[2].trim()) : 0L;
                    CacheStrategy cacheStrategy = new CacheStrategy(split[1].trim(), maxSize, maxIdle, maxLive);
                    cacheStrategyMap.put(cacheStrategy.getName(), cacheStrategy);
                    log.debugf("load CacheStrategy %s", cacheStrategy);
                } catch (Exception e) {
                    log.errorf("failed to load cache [%s]", entry.getKey());
                }
            } else if (split.length == 3) {
                // cache.name.maxSize=10000
                try {
                    String type = split[2].trim();
                    long value = Long.parseLong(entry.getValue());
                    String name = split[1].trim();
                    CacheStrategy cacheStrategy = map.get(name);
                    if (cacheStrategy == null) {
                        cacheStrategy = new CacheStrategy(name);
                        map.put(name, cacheStrategy);
                    }
                    if ("maxSize".equalsIgnoreCase(type)) {
                        cacheStrategy.setMaxSize(value);
                    } else if ("maxIdle".equalsIgnoreCase(type)) {
                        cacheStrategy.setMaxIdle(value);
                    } else if ("maxLive".equalsIgnoreCase(type)) {
                        cacheStrategy.setMaxLive(value);
                    }
                } catch (Exception e) {
                    log.errorf("failed to apply cache rule [%s]", entry.getKey());
                }
            }
        });
        map.values().stream().forEach(cacheStrategy -> log.debugf("load CacheStrategy %s", cacheStrategy));
        cacheStrategyMap.putAll(map);
        if (!cacheStrategyMap.containsKey(CacheStrategy.DEFAULT)) {
            // 没有默认的话,加一个默认
            cacheStrategyMap.put(CacheStrategy.DEFAULT, new CacheStrategy(CacheStrategy.DEFAULT, 10000, 0, 0));
            log.debugf("load DEFAULT CacheStrategy %s", cacheStrategyMap.get(CacheStrategy.DEFAULT));
        }
    }

}

编译不能通过

   this.updateStrategy = Lang.isEmptyArray(updateStrategyNames) ? k -> false : ioc.get(UpdateStrategy.class, updateStrategyNames[0]);

原本UpdateStrategy方法

package org.nutz.boot.starter.caffeine;

public interface UpdateStrategy {

    /**
     * 是否需要强制更新缓存
     * @param key 缓存键
     * @return should update ?
     */
    boolean shouldUpdate(String key);

}

这个要如何修改 才能编译呢

  this.updateStrategy = Lang.isEmptyArray(updateStrategyNames) ? k -> false : ioc.get(UpdateStrategy.class, updateStrategyNames[0]);
3 回复

为新增的方法添加default及默认实现,jdk8支持

明白意思了 但是 不知道 怎么写 有实例代码吗

酱紫调整

package org.nutz.boot.starter.caffeine;


public interface UpdateStrategy {

    /**
     * 是否需要强制更新缓存
     * @param key 缓存键
     * @return should update ?
     */
    boolean shouldUpdate(String key);

    /**
     * 清除全部缓存
     * @param key
     * @return
     */
    boolean invalidateAll(String key);

    default boolean invalidateAll(){
        return false;
    }

    default boolean shouldUpdate(){
        return false;
    }
}

k -> false 还是无法编译通过

 this.updateStrategy = Lang.isEmptyArray(updateStrategyNames) ? k -> false : ioc.get(UpdateStrategy.class, updateStrategyNames[0]);
添加回复
请先登陆
回到顶部