先上代码:
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);