1、特性
- 使用key -value形式数据结构,读写简单。
- 遵循开闭原则
- 线程安全
- 良好的扩展性
- 良好的数据安全性(key不覆盖、方法可见性限制、使用入口唯一)
2、涉及技术\知识点\设计思路
-
spring
作用 :本案例基于spring开发,做待缓存数据初始化到容器用。 -
java 1.8+
作用:JDK1.5 后提供了线程安全、且性能优于HashTable的并发容器:ConcurrentHashMap,作为本案例使用的数据存储容器。另外示例源码使用到JDK1.8特性,故使用1.8+。 -
策略模式
作用:公共方法抽象定义成抽象类,不同的场景业务数据类单独封装成策略子类,去继承实现,这样便提供了良好的扩展性。除此之外,提供唯一使用入口。用户不必关心底层细节实现,一步到位。 -
java四大修饰符
作用:保证底层核心定义不被修改
3、源码
- 抽象策略类
/**
* 抽象缓存公用方法
*/
public abstract class AbstractDataMemory {
protected void init(Class<? extends AbstractDataMemory> clazz, HashMap<String,String> initVal){
DataMemory.getInstance(clazz).init(initVal);
}
}
- 具体策略类
@Service
public class Amemory extends AbstractDataMemory implements ApplicationListener<ContextRefreshedEvent>
{
private static final Logger logger = Logger.getLogger(Amemory.class);
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();
String displayName = contextRefreshedEvent.getApplicationContext().getDisplayName();
displayName = org.apache.commons.lang3.StringUtils.isNotEmpty(displayName)?displayName.replace(" ", ""):"";
logger.error("xx业务数据初始化:"+"displayName:"+displayName);
//保证只执行一次
if ("RootWebApplicationContext".equals(displayName)) {
logger.error("xx业务数据初始化-开始");
//需要执行的方法
init(Amemory.class,getDataForMemory(applicationContext));
}
}
public HashMap<String,String> getDataForMemory(ApplicationContext applicationContext) {
//通过Dao类注解名可直接获取Dao类,但必须保证IxxDao只有一个实现类(正常情况只有一个)
// IxxDao xxDao = (IxxDao)applicationContext.getBean("clientDao");
HashMap<String,String> result = new HashMap<>();
// List<xx> all = xxDao.findAll();
// if(CollectionUtils.isNotEmpty(all)){
// for(xx xx : all){
//
// result.put(xx.getUuid(),xx);
// }
// }
logger.error("xx数据:"+ result);
return result;
}
}
- 统一管理入口类
/**
* @Description 缓存入口类(策略模式)
* @Author lzj
* @Date 2022-02-05
*/
public class DataMemory {
// private static final Logger logger = Logger.getLogger(DataMemory.class);
//使用 ConcurrentHashMap 存放数据,保证线程安全
private static ConcurrentHashMap<String,String> container = new ConcurrentHashMap<>();
//持有抽象工具类
private AbstractDataMemory memory;
//key修饰前缀,默认使用类名做前缀
private String decoratePrefix;
private DataMemory(AbstractDataMemory memory,String prefix){
this.memory = memory;
this.decoratePrefix = prefix;
}
/**
* 实例化具体某个缓存对象(继承AbstractDataMemory)
* @param clazz
* @return
*/
public static DataMemory getInstance(Class<? extends AbstractDataMemory> clazz){
try {
Object o = clazz.newInstance();
String className = clazz.getSimpleName();
return new DataMemory((AbstractDataMemory)o,className);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
/**
* 设置缓存,不能为空,否则concurrentHashMap报空指针异常
* @param key
* @param value
*/
public void set(String key,String value){
if(StringUtils.isEmpty(key) || StringUtils.isEmpty(value)){
return;
}
// String decorateKey = memory.decorateKey(key);
String decorateKey = this.decoratePrefix+key;
container.put(decorateKey,value);
}
/**
* 从缓存中获取数据
* @param key
* @return
*/
public String get(String key){
// String decorateKey = memory.decorateKey(key);
String decorateKey = this.decoratePrefix+key;
return container.get(decorateKey);
}
/**
* 初始化进缓存对象
* @param map
*/
protected void init(HashMap<String, String> map){
// container.clear();
if(map.size()>0){
map.forEach(
(key,value) ->{
set(key,value);
}
);
}
}
/**
* 删除某个缓存
* @param key
*/
public void removeOne(String key){
// String decorateKey = memory.decorateKey(key);
String decorateKey = this.decoratePrefix+key;
container.remove(decorateKey);
}
/**
* 根据Key前缀筛选容器中对应的实例缓存
* @return
*/
public HashMap<String,String> getCurrentData(){
// String keyPrefix = memory.getKeyPrefix();
String keyPrefix = this.decoratePrefix;
HashMap<String,String> resultMap = new HashMap<>();
if(container.size()>0){
container.forEach((key,value) ->{
if(key.startsWith(keyPrefix)){
resultMap.put(key,value);
}
});
}
return resultMap;
}
}
-
使用示例