聊聊Spring Cache的缓存抽象与JSR107缓存抽象JCache,并使用API方式使用Spring Cache【享学Spring】(中)

简介: 聊聊Spring Cache的缓存抽象与JSR107缓存抽象JCache,并使用API方式使用Spring Cache【享学Spring】(中)

SimpleCacheManager


// @since 3.1
public class SimpleCacheManager extends AbstractCacheManager {
  private Collection<? extends Cache> caches = Collections.emptySet();
  public void setCaches(Collection<? extends Cache> caches) {
    this.caches = caches;
  }
  @Override
  protected Collection<? extends Cache> loadCaches() {
    return this.caches;
  }
}


最简单的一个CacheManager,它的caches都必须由调用者手动指定。若交给容器管理会自动执行afterPropertiesSet()方法,否则需要手动自己调用cacheManager.afterPropertiesSet();,自己放进去的setCaches才会生效~


NoOpCacheManager


一种基本的、无操作的CacheManager实现,适用于禁用缓存,通常用于在没有实际存储的情况下作为缓存声明。

ConcurrentMapCacheManager(重要)

// @since 3.1
public class ConcurrentMapCacheManager implements CacheManager, BeanClassLoaderAware {
  private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<>(16);
  // true表示:若为null,就新创建一个缓存添加进去
  private boolean dynamic = true;
  // 是否允许value为null
  private boolean allowNullValues = true;
  // 指定此缓存管理器是存储每个条目的副本,还是存储其所有缓存的引用
  // 影响到ConcurrentMapCache对value值的存储~~~
  // false表示:存储它自己(引用)
  // true表示:存储一个副本(对序列化有要求~~~) 很少这么使用~~~
  private boolean storeByValue = false;
  public ConcurrentMapCacheManager() {
  }
  public ConcurrentMapCacheManager(String... cacheNames) {
    setCacheNames(Arrays.asList(cacheNames));
  }
  public void setCacheNames(@Nullable Collection<String> cacheNames) {
    if (cacheNames != null) {
      for (String name : cacheNames) {
        this.cacheMap.put(name, createConcurrentMapCache(name));
      }
      this.dynamic = false; // 手动设置了,就不允许在动态创建了
    } else {
      this.dynamic = true;
    }
  }
  protected Cache createConcurrentMapCache(String name) {
    // isStoreByValue=true需要存储值的副本的时候,才对序列化有要求~~~否则直接存引用即可
    SerializationDelegate actualSerialization = (isStoreByValue() ? this.serialization : null);
    return new ConcurrentMapCache(name, new ConcurrentHashMap<>(256), isAllowNullValues(), actualSerialization);
  }
  @Override
  public void setBeanClassLoader(ClassLoader classLoader) {
    this.serialization = new SerializationDelegate(classLoader);
    if (isStoreByValue()) {
      // 重新创建Cache 因为要副本嘛
      recreateCaches();
    }
  }
  private void recreateCaches() {
    for (Map.Entry<String, Cache> entry : this.cacheMap.entrySet()) {
      entry.setValue(createConcurrentMapCache(entry.getKey()));
    }
  }
  @Override
  @Nullable
  public Cache getCache(String name) {
    Cache cache = this.cacheMap.get(name);
    // dynamic=true  为null的时候会动态创建一个
    if (cache == null && this.dynamic) {
      synchronized (this.cacheMap) {
        cache = this.cacheMap.get(name);
        if (cache == null) {
          cache = createConcurrentMapCache(name);
          this.cacheMap.put(name, cache);
        }
      }
    }
    return cache;
  }
  @Override
  public Collection<String> getCacheNames() {
    return Collections.unmodifiableSet(this.cacheMap.keySet());
  }
  ...
}


它的缓存存储是基于内存的,所以它的生命周期是与应用关联的,对于生产级别的大型企业级应用程序,这可能并不是理想的选择,但它用于本地自己测试是个很好的选择。


CompositeCacheManager


// @since 3.1  
public class CompositeCacheManager implements CacheManager, InitializingBean {
  // 内部聚合管理着一批CacheManager
  private final List<CacheManager> cacheManagers = new ArrayList<>();
  // 若这个为true,则可以结合NoOpCacheManager实现效果~~~
  private boolean fallbackToNoOpCache = false;
  public CompositeCacheManager() {
  }
  public CompositeCacheManager(CacheManager... cacheManagers) {
    setCacheManagers(Arrays.asList(cacheManagers));
  }
  // 也可以调用此方法,来自己往里面添加(注意是添加)CacheManager们
  public void setCacheManagers(Collection<CacheManager> cacheManagers) {
    this.cacheManagers.addAll(cacheManagers);
  }
  public void setFallbackToNoOpCache(boolean fallbackToNoOpCache) {
    this.fallbackToNoOpCache = fallbackToNoOpCache;
  }
  // 如果fallbackToNoOpCache=true,那么在这个Bean初始化完成后,也就是在末尾添加一个NoOpCacheManager
  // 当然fallbackToNoOpCache默认值是false
  @Override
  public void afterPropertiesSet() {
    if (this.fallbackToNoOpCache) {
      this.cacheManagers.add(new NoOpCacheManager());
    }
  }
  // 找到一个cache不为null的就return了~
  @Override
  @Nullable
  public Cache getCache(String name) {
    for (CacheManager cacheManager : this.cacheManagers) {
      Cache cache = cacheManager.getCache(name);
      if (cache != null) {
        return cache;
      }
    }
    return null;
  }
  // 可以看到返回的是所有names,并且用的set
  @Override
  public Collection<String> getCacheNames() {
    Set<String> names = new LinkedHashSet<>();
    for (CacheManager manager : this.cacheManagers) {
      names.addAll(manager.getCacheNames());
    }
    return Collections.unmodifiableSet(names);
  }
}


CompositeCacheManager要通过一个或更多的缓存管理器来进行配置,它会迭代这些缓存管理器,以查找之前所缓存的值。

看完CacheManager,再看看Cache这个接口:


public interface Cache {
  String getName();
  // 返回本地存储的那个。比如ConcurrentMapCache本地就是用的一个ConcurrentMap
  Object getNativeCache();
  // 就是用下面的ValueWrapper把值包装了一下而已~
  @Nullable
  ValueWrapper get(Object key);
  @Nullable
  <T> T get(Object key, @Nullable Class<T> type);
  @Nullable
  <T> T get(Object key, Callable<T> valueLoader);
  void put(Object key, @Nullable Object value);
  // @since 4.1
  // 不存在旧值直接put就先去了返回null,否则返回旧值(并且不会把新值put进去)
  @Nullable
  ValueWrapper putIfAbsent(Object key, @Nullable Object value);
  // 删除
  void evict(Object key);
  // 清空
  void clear();
  @FunctionalInterface
  interface ValueWrapper {
    @Nullable
    Object get();
  }
}


它的继承树非常简单,如下:

image.png


相关文章
|
5月前
|
前端开发 Java API
利用 Spring WebFlux 技术打造高效非阻塞 API 的完整开发方案与实践技巧
本文介绍了如何使用Spring WebFlux构建高效、可扩展的非阻塞API,涵盖响应式编程核心概念、技术方案设计及具体实现示例,适用于高并发场景下的API开发。
456 0
|
4月前
|
人工智能 Java 机器人
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
Spring AI Alibaba集成Ollama,基于Java构建本地大模型应用,支持流式对话、knife4j接口可视化,实现高隐私、免API密钥的离线AI服务。
3829 2
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
|
5月前
|
缓存 监控 Linux
Linux系统清理缓存(buff/cache)的有效方法。
总结而言,在大多数情形下你不必担心Linux中buffer与cache占用过多内存在影响到其他程序运行;因为当程序请求更多内存在没有足够可用资源时,Linux会自行调整其占有量。只有当你明确知道当前环境与需求并希望立即回收这部分资源给即将运行重负载任务之前才考虑上述方法去主动干预。
1772 10
|
5月前
|
缓存 Java API
Spring WebFlux 2025 实操指南详解高性能非阻塞 API 开发全流程核心技巧
本指南基于Spring WebFlux 2025最新技术栈,详解如何构建高性能非阻塞API。涵盖环境搭建、响应式数据访问、注解与函数式两种API开发模式、响应式客户端使用、测试方法及性能优化技巧,助你掌握Spring WebFlux全流程开发核心实践。
1076 0
|
9月前
|
存储 人工智能 Java
Spring AI与DeepSeek实战四:系统API调用
在AI应用开发中,工具调用是增强大模型能力的核心技术,通过让模型与外部API或工具交互,可实现实时信息检索(如天气查询、新闻获取)、系统操作(如创建任务、发送邮件)等功能;本文结合Spring AI与大模型,演示如何通过Tool Calling实现系统API调用,同时处理多轮对话中的会话记忆。
1898 57
|
7月前
|
Java API 网络架构
基于 Spring Boot 框架开发 REST API 接口实践指南
本文详解基于Spring Boot 3.x构建REST API的完整开发流程,涵盖环境搭建、领域建模、响应式编程、安全控制、容器化部署及性能优化等关键环节,助力开发者打造高效稳定的后端服务。
1067 1
|
6月前
|
存储 缓存 NoSQL
Spring Cache缓存框架
Spring Cache是Spring体系下的标准化缓存框架,支持多种缓存(如Redis、EhCache、Caffeine),可独立或组合使用。其优势包括平滑迁移、注解与编程两种使用方式,以及高度解耦和灵活管理。通过动态代理实现缓存操作,适用于不同业务场景。
563 0
|
存储 安全 Java
Spring Boot 编写 API 的 10条最佳实践
本文总结了 10 个编写 Spring Boot API 的最佳实践,包括 RESTful API 设计原则、注解使用、依赖注入、异常处理、数据传输对象(DTO)建模、安全措施、版本控制、文档生成、测试策略以及监控和日志记录。每个实践都配有详细的编码示例和解释,帮助开发者像专业人士一样构建高质量的 API。
474 9
|
Java 测试技术 API
详解Swagger:Spring Boot中的API文档生成与测试工具
详解Swagger:Spring Boot中的API文档生成与测试工具
1059 4
|
人工智能 Java API
Spring AI Fluent API:与AI模型通信的流畅体验
【11月更文挑战第24天】随着人工智能(AI)技术的飞速发展,越来越多的应用场景开始融入AI技术以提升用户体验和系统效率。在Java开发中,与AI模型通信成为了一个重要而常见的需求。为了满足这一需求,Spring AI引入了ChatClient,一个提供流畅API(Fluent API)的客户端,用于与各种AI模型进行通信。本文将深入探讨ChatClient的底层原理、业务场景、概念、功能点,并通过Java代码示例展示如何使用Fluent API与AI模型进行通信。
504 0