All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.bootfastconfig.cache.l2cache.L2Cache Maven / Gradle / Ivy

Go to download

Parent pom providing dependency and plugin management for applications built with Maven

The newest version!
package com.github.bootfastconfig.cache.l2cache;

import com.github.bootfastconfig.cache.CacheMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.support.AbstractValueAdaptingCache;

import java.util.concurrent.Callable;
import java.util.function.Consumer;

/**
 * @author mister
 */
public class L2Cache extends AbstractValueAdaptingCache {

    private final static Logger log = LoggerFactory.getLogger(L2Cache.class);

    private String name;


    private Cache cache1;


    private Cache cache2;


    private String topic;

    private Object lock = new Object();


    private Consumer eventPublisher;


    protected L2Cache(boolean allowNullValues) {
        super(allowNullValues);
    }

    public L2Cache(String name, String topic, Cache cache1, Cache cache2, Consumer eventPublisher) {
        super(true);
        this.topic = topic;
        this.name = name;
        this.cache1 = cache1;
        this.cache2 = cache2;
        this.eventPublisher = eventPublisher;
    }


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

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

    @SuppressWarnings("unchecked")
    @Override
    public  T get(Object key, Callable valueLoader) {
        Object value = lookup(key);
        if (value != null) {
            return (T) value;
        }
        synchronized (lock) {
            value = lookup(key);
            if (value != null) {
                return (T) value;
            }
            try {
                value = valueLoader.call();
            } catch (Exception ex) {
                throw new ValueRetrievalException(key, valueLoader, ex);
            }
            Object storeValue = toStoreValue(value);
            put(key, storeValue);
            return (T) value;
        }
    }


    @Override
    public void put(Object key, Object value) {
        if (!super.isAllowNullValues() && value == null) {
            this.evict(key);
            return;
        }
        cache2.put(key, value);
        cache1.put(key, value);
        eventPublisher.accept(getCacheMessage(key));
    }


    private CacheMessage getCacheMessage(Object key) {
        return new CacheMessage(this.name, key, this.hashCode(), this.topic);
    }

    @Override
    public ValueWrapper putIfAbsent(Object key, Object value) {
        ValueWrapper valueWrapper = null;
        Object prevValue = null;
        // 考虑使用分布式锁,或者将redis的setIfAbsent改为原子性操作
        synchronized (lock) {
            valueWrapper = cache2.get(key);
            if (valueWrapper != null) prevValue = valueWrapper.get();
            if (prevValue == null) {
                valueWrapper = cache2.putIfAbsent(key, value);
                eventPublisher.accept(getCacheMessage(key));
                cache1.put(key, toStoreValue(value));
            }
        }
        return valueWrapper;
    }

    @Override
    public void evict(Object key) {
        cache2.evict(key);
        cache1.evict(key);
        eventPublisher.accept(getCacheMessage(key));
    }

    @Override
    public void clear() {
        cache2.clear();
        cache1.clear();
        eventPublisher.accept(getCacheMessage(null));
    }


    @Override
    protected Object lookup(Object key) {
        Object value = null;
        ValueWrapper valueWrapper = cache1.get(key);
        if (valueWrapper != null) value = valueWrapper.get();
        if (value != null) {
            log.debug("get cache from ehcache, the key is : {}", key);
            return value;
        }
        valueWrapper = cache2.get(key);
        if (valueWrapper != null) value = valueWrapper.get();
        if (value != null) {
            log.debug("get cache from redis and put in ehcache, the key is : {}", key);
            cache1.put(key, value);
        }
        return value;
    }


    /**
     * @param key
     * @description 清理本地缓存
     */
    private void clearLocal(Object key) {
        log.debug("clear local cache, the key is : {}", key);
        if (key == null) {
            cache1.clear();
        } else {
            cache1.evict(key);
        }
    }

    /**
     * 根据CacheMessage 进行清除缓存
     *
     * @param cacheMessage
     */
    public void clearCache(CacheMessage cacheMessage) {
        if (this.name.equals(cacheMessage.getCacheName()) && this.hashCode() != cacheMessage.getSender()) {
            clearLocal(cacheMessage.getKey());
        }
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy