本地缓存实现方式

先上代码:


import java.util.concurrent.ConcurrentHashMap;

public class LocalCache {
    private static ConcurrentHashMap<Object, LocalCacheObjectLoader> objectLoaderMap = new ConcurrentHashMap();
    private static LocalCacheMap cacheMap = new LocalCacheMap();

    public LocalCache() {
    }

    public static <ObjectType> void addObjectLoader(Class<ObjectType> objectType, LocalCacheObjectLoader objectLoader) {
        objectLoaderMap.put(objectType, objectLoader);
    }

    public static void addObjectLoader(Object objectType, LocalCacheObjectLoader objectLoader) {
        objectLoaderMap.put(objectType, objectLoader);
    }

    public static void setObjectValue(Object objectType, Object objectKey, Object objectValue) {
        LocalCacheObjectMap objectMap = getObjectMap(objectType);
        LocalCacheObject object = new LocalCacheObject();
        object.setValue(objectValue);
        objectMap.put(objectKey, object);
    }

    public static <ObjectType> ObjectType getObjectValue(Object objectType, Object objectKey) {
        LocalCacheObjectLoader objectLoader = (LocalCacheObjectLoader)objectLoaderMap.get(objectType);
        long updateInterval = objectLoader.updateInterval();
        return getObjectValue(objectType, objectKey, updateInterval);
    }

    public static <ObjectType> ObjectType getObjectValue(Object objectType, Object objectKey, long updateInterval) {
        LocalCacheObjectMap objectMap = getObjectMap(objectType);
        LocalCacheObject object = (LocalCacheObject)objectMap.get(objectKey);
        if (object == null || object.isExpired()) {
            object = load(objectType, objectKey, updateInterval, objectMap);
        }

        return object == null ? null : object.getValue();
    }

    public static <ObjectType> void setObjectValue(Class<ObjectType> objectType, Object objectKey, ObjectType objectValue) {
        setObjectValue(objectType, objectKey, objectValue, 0L);
    }

    public static <ObjectType> void setObjectValue(Class<ObjectType> objectType, Object objectKey, ObjectType objectValue, long updateInterval) {
        LocalCacheObjectMap objectMap = getObjectMap(objectType);
        LocalCacheObject object = new LocalCacheObject();
        object.setValue(objectValue);
        object.setUpdateInterval(updateInterval);
        objectMap.put(objectKey, object);
    }

    private static LocalCacheObject load(Object objectType, Object objectKey, long updateInterval, LocalCacheObjectMap objectMap) {
        LocalCacheObjectLoader objectLoader = (LocalCacheObjectLoader)objectLoaderMap.get(objectType);
        if (objectLoader != null) {
            LocalCacheObject object = new LocalCacheObject();
            Object objectValue = objectLoader.load(objectKey);
            object.setUpdateInterval(updateInterval);
            object.setValue(objectValue);
            objectMap.put(objectKey, object);
            return object;
        } else {
            return null;
        }
    }

    private static LocalCacheObjectMap getObjectMap(Object objectType) {
        LocalCacheObjectMap objectMap = (LocalCacheObjectMap)cacheMap.get(objectType);
        if (objectMap == null) {
            objectMap = new LocalCacheObjectMap();
            cacheMap.put(objectType, objectMap);
        }

        return objectMap;
    }

    public static long getTimeStamp() {
        long now = System.currentTimeMillis();
        return now / 1000L;
    }
import java.util.concurrent.ConcurrentHashMap;

public class LocalCacheMap extends ConcurrentHashMap<Object, LocalCacheObjectMap> {
    public LocalCacheMap() {
    }
}

public class LocalCacheObject {
    private Object value;
    private long nextUpdateTime = 0L;
    private long updateInterval = 0L;

    public LocalCacheObject() {
    }

    public Object getValue() {
        return this.value;
    }

    public void setValue(Object value) {
        this.value = value;
        this.setUpdateInterval(this.updateInterval);
    }

    public boolean isExpired() {
        if (this.updateInterval > 0L) {
            return this.nextUpdateTime < LocalCache.getTimeStamp();
        } else {
            return false;
        }
    }

    public void setUpdateInterval(long interval) {
        this.updateInterval = interval;
        if (this.updateInterval > 0L) {
            this.nextUpdateTime = LocalCache.getTimeStamp() + this.updateInterval;
        }

    }
}

public interface LocalCacheObjectLoader {
    Object load(Object objectKey);

    long updateInterval();
}

import java.util.concurrent.ConcurrentHashMap;

public class LocalCacheObjectMap extends ConcurrentHashMap<Object, LocalCacheObject> {
    public LocalCacheObjectMap() {
    }
}

import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LocalCachePool {
    private ConcurrentHashMap<String, LocalCacheObject> objects = new ConcurrentHashMap();
    private static final Logger logger = LoggerFactory.getLogger(LocalCachePool.class);

    public LocalCachePool() {
    }

    @Pointcut("@annotation(monkey.common.SaveToLocalCache)")
    public void getValue() {
    }

    @Around("getValue()")
    public Object execute(ProceedingJoinPoint point) throws Throwable {
        try {
            MethodSignature signature = (MethodSignature)point.getSignature();
            Method method = signature.getMethod();
            StringBuilder keyBuilder = new StringBuilder();
            keyBuilder.append(point.getTarget().getClass().getTypeName());
            keyBuilder.append(".");
            keyBuilder.append(method.getName());
            String key = keyBuilder.toString();
            LocalCacheObject object = null;
            if (this.objects.containsKey(key)) {
                object = (LocalCacheObject)this.objects.get(key);
                if (object.isExpired()) {
                    Object value = point.proceed();
                    object.setValue(value);
                }
            } else {
                object = new LocalCacheObject();
                long updateInterval = (long)((SaveToLocalCache)method.getAnnotation(SaveToLocalCache.class)).updateIntervalSeconds();
                object.setUpdateInterval(updateInterval);
                Object value = point.proceed();
                object.setValue(value);
                this.objects.put(key, object);
            }

            return object.getValue();
        } catch (Exception var10) {
            logger.error(var10.getMessage(), var10);
            return null;
        }
    }

    public void removeCache(String key) {
        if (this.objects.containsKey(key)) {
            this.objects.remove(key);
        }

    }
}

import java.util.HashMap;
import java.util.Map;
import org.springframework.core.NamedThreadLocal;

public class LocalThreadContextHolder {
    private static final ThreadLocal<Map<String, Object>> holder = new NamedThreadLocal("Local thread context");

    public LocalThreadContextHolder() {
    }

    public static void set(String key, Object data) {
        Map<String, Object> dataMap = (Map)holder.get();
        if (dataMap == null) {
            dataMap = new HashMap();
            holder.set(dataMap);
        }

        ((Map)dataMap).put(key, data);
    }

    public static Object get(String key) {
        Map<String, Object> dataMap = (Map)holder.get();
        return dataMap == null ? null : dataMap.get(key);
    }

    public static void reset() {
        holder.remove();
    }
}

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;



import javax.annotation.PostConstruct;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.*;
import java.util.stream.Collectors;

public abstract class LocalCacheBase<T> {

    private Logger logger = null ;
    //private volatile List<T> data ;

    private Class targetClazz ;

    private LocalCacheBase targetObj ;

    public abstract void init() ;

    @Autowired
    ObjectContainer objectContainer ;
    @PostConstruct
    public void _init(){
        initLogger() ;
        init();
    }

    public abstract List<T> selectAll() ;

    public void updateCache(){
        String value = this.getClass().getTypeName() + ".selectAll";
        EventProducer.publish("v1.local.cache.update", value);
    }



    LocalCacheBase getTargetObj(){
        if(targetObj==null){
            targetObj = objectContainer.getObject(this.getClass());
        }
        return targetObj ;
    }

    /**
     * 通过spring容器获取对象,不然无法进入monkey的缓存管理
     * @return
     */
    public List<T> getAllData(){
        List list = getTargetObj().selectAll();
        if(list==null){
            return new ArrayList<>() ;
        }
        return list;
    }

    /**
     * 初始化
     * @param serviceClazz 服务类
     */
    public Object init(/*Class targetClazz ,*/ Class serviceClazz){

        //this.targetClazz = targetClazz ;
        //targetObj = (LocalCacheBase) ObjectContainer.getObject(targetClazz);

        logger.info("当前对象:{}",this.getClass());
        //服务层对象尝试从当前应用中获取
        Object serviceObject = null ;
        try {
            serviceObject = objectContainer.getObject(serviceClazz) ;
            logger.info("从当前应用中获取bean对象:{}",serviceClazz);
        }catch (Exception e){
            serviceObject = ServiceBus.create(serviceClazz) ;
            logger.info("远程获取bean对象:{}",serviceClazz);
        }
        return serviceObject ;
    }


    private void initLogger(){
        logger = LoggerFactory.getLogger(this.getClass()) ;
    }

    public List<T> find(T t){

        if(t==null){
            return getAllData() ;
        }

        NotNullFieldEntity notNullField = findNotNullField(t);
        Map<String, Object> notNullFieldValue = notNullField.getNotNullFieldValue();

        if(notNullFieldValue.size()==0)return getAllData() ;
        //根据获取到的非空字段去所有数据中对比
        List<T> allData = getAllData();
        return allData.stream().filter(item->{
            return compareData(item,notNullField) ;
        }).collect(Collectors.toList()) ;

    }

    /**
     *  根据条件,匹配到第一个就返回
     * @param t
     * @return
     */
    public T findOne(T t){
        if(t==null){
            return null ;
        }

        NotNullFieldEntity notNullField = findNotNullField(t);
        Map<String, Object> notNullFieldValue = notNullField.getNotNullFieldValue();
        Map<String, Method> notNullFieldRM = notNullField.getNotNullFieldRM();

        if(notNullFieldValue.size()==0)return getAllData().get(0) ;

        List<T> allData = getAllData();
        for (T item : allData) {
            //对比成功就直接返回
            if(compareData(item,notNullField)){
                return item ;
            }
        }

        return null;
    }


    /**
     * 根据ID查询单个数据
     * @param id
     * @return
     */
    public T find(Long id){

        if(id==null)return null;
        for (T item : getAllData()) {

            try {
                Method getIdMethod = item.getClass().getMethod("getId", null);
                long invoke = (long) getIdMethod.invoke(item, null);
                if(invoke==id){
                    //logger.info("ID:{} 命中",id);
                    return item ;
                }
            }catch (Exception e){
                logger.error(e.getMessage(), e);
            }
        }


        return null;
    }

    /**
     * 根据多个id查询数据
     * @param ids
     * @return
     */
    public List<T> find(Collection<Long> ids){
        List<T> datas = new ArrayList<>() ;

        if(ids==null){
            throw new NullPointerException("参数不可为空") ;
        }
        //去重
        Set<Long> idSet = new HashSet<>(ids) ;
        idSet.forEach(id->{
            T t = find(id) ;
            if(t!=null){
                datas.add(find(id)) ;
            }
        });
        return datas;
    }

    /**
     * 手动删除本地缓存
     */
    public void removeAll(){
        objectContainer.getObject(LocalCachePool.class).removeCache(getClass().getTypeName()+".selectAll"); ;
    }
    /**
     * 实例化传入进来的泛型
     * @return
     */
    private T getInstanceOfType(){
        try {
            ParameterizedType superClass  = (ParameterizedType) getClass().getGenericSuperclass();
            Class<T> type = (Class<T>) superClass.getActualTypeArguments()[0];
            return type.newInstance() ;
        }catch (Exception e){
            logger.error(e.getMessage(), e);
        }

        return null ;

    }

    /**
     * 获取传入对象中,字段数据不为空的字段数据和字段read方法
     * @param t
     * @return
     */
    private NotNullFieldEntity findNotNullField(T t){
        Map<String,Object> notNullFieldValue = new HashMap<>() ;
        Map<String,Method> notNullFieldRM = new HashMap<>( );
        //获取传入对象中,非空字段
        PropertyDescriptor propertyDescriptor = null ;
        String fieldName = null ;
        Method readMethod = null ;
        Class tCalzz = t.getClass() ;
        for (Field declaredField : t.getClass().getDeclaredFields()) {
            try {
                fieldName = declaredField.getName() ;
                //序列化标识字段跳过
                if(fieldName.equals("serialVersionUID"))continue;

                propertyDescriptor = new PropertyDescriptor(fieldName,tCalzz) ;
                readMethod = propertyDescriptor.getReadMethod() ;

                Object object =  readMethod.invoke(t) ;

                if (object!=null){
                    notNullFieldValue.put(fieldName,object) ;
                    notNullFieldRM.put(fieldName,readMethod) ;
                }

            }catch (Exception e){
                logger.error(e.getMessage(), e);
            }

        }
        NotNullFieldEntity notNullFieldEntity = new NotNullFieldEntity() ;
        notNullFieldEntity.setNotNullFieldValue(notNullFieldValue);
        notNullFieldEntity.setNotNullFieldRM(notNullFieldRM);

        return notNullFieldEntity;
    }

    /**
     * 对比不为空的数据字段值是否相等
     * @param t
     * @param notNullFieldEntity
     * @return
     */
    private boolean compareData(T t , NotNullFieldEntity notNullFieldEntity){
        Map<String, Object> notNullFieldValue = notNullFieldEntity.getNotNullFieldValue();
        Map<String, Method> notNullFieldRM = notNullFieldEntity.getNotNullFieldRM();
        String fieldName ;
        boolean flag = true ;
        for (Map.Entry<String, Object> valueEntry : notNullFieldValue.entrySet()) {
            fieldName = valueEntry.getKey() ;
            try {
                //logger.info("对比字段:{},传入值:{},当前值:{}",fieldName2,valueEntry.getValue(),notNullFiledRM.get(fieldName2).invoke(item));
                if(!valueEntry.getValue().equals(notNullFieldRM.get(fieldName).invoke(t))){
                    flag = false ;
                    break ;
                }
            }catch (Exception e){
                logger.error(e.getMessage(), e);
            }
        }
        return flag ;
    }

    /**
     * 非空字段实体
     */
    class NotNullFieldEntity{
        private Map<String,Object> notNullFieldValue;
        private Map<String,Method> notNullFieldRM;

        public Map<String, Object> getNotNullFieldValue() {
            return notNullFieldValue;
        }

        public void setNotNullFieldValue(Map<String, Object> notNullFieldValue) {
            this.notNullFieldValue = notNullFieldValue;
        }

        public Map<String, Method> getNotNullFieldRM() {
            return notNullFieldRM;
        }

        public void setNotNullFieldRM(Map<String, Method> notNullFieldRM) {
            this.notNullFieldRM = notNullFieldRM;
        }
    }

对应模块应用:

@Component
public class UserLocalCacheManager extends LocalCacheBase<User> {

    private UserService userService ;

    @Override
    public void init() {
        userService = (UserService) init(userService.class);
    }

    @SaveToLocalCache(updateIntervalSeconds=300)
    @Override
    public List<User> selectAll() {
        return userService.findAll().getData();
    }

}

在Service层里面注入后,引用;

 @Autowired
    private UserLocalCacheManager userLocalCacheManager;

在方法中调用就能拿到对应的值了
    User user = userLocalCacheManager.find(userId);

猜你喜欢

转载自blog.csdn.net/tmuffamd/article/details/128931184
今日推荐