Spring Cache 与消息集成

共 33 题
📑 题目列表 33 题
#
★★★

1. @Cacheable 的 sync=true 在高并发下避免击穿(Cache Stampede)的实现

请说明 @Cacheable 的 sync=true 在高并发下如何避免缓存击穿(Cache Stampede)?

  • sync=true 开启同步缓存
  • 缓存击穿(Stampede)问题
  • 单线程加载防并发穿透

@Cacheable 的 sync=true 开启同步缓存:当缓存不存在时,多个并发线程同时请求同一个 key,sync 模式下只有一个线程真正执行方法加载并写缓存,其余线程等待该线程完成后读取缓存,从而避免缓存击穿(Cache Stampede,即大量并发同时穿透到数据库)。sync=true 通过在缓存层加锁(Caffeine 的同步加载)保证单线程加载,适用于初始化开销大、并发访问密集的场景。注意:sync=true 只支持单 key 的 Cacheable,不支持并发加载多个 key 的组合。

sync=true 解决"缓存失效瞬间并发穿透"问题,通过单线程加载 + 等待机制避免雪崩式数据库压力。是缓存击穿的标准防护。

#
★★★

2. @Cacheable 缓存值的序列化(GenericJackson2JsonRedisSerializer)

请说明 @Cacheable 缓存值的序列化,特别是 GenericJackson2JsonRedisSerializer 的使用?

  • 缓存值序列化机制
  • GenericJackson2JsonRedisSerializer 的 JSON 序列化
  • 类型信息与反序列化

@Cacheable 缓存数据需要序列化存储。使用 Redis 缓存时,可通过 RedisCacheConfiguration 配置值序列化器。GenericJackson2JsonRedisSerializer 是 Jackson 的 JSON 序列化器,把对象序列化为 JSON 字符串,并保留类型信息(@class 字段),反序列化时据此还原对象类型,适合存储复杂对象且人类可读。相比默认 JDK 序列化(JdkSerializationRedisSerializer),JSON 序列化可读、跨语言、体积小。使用时需注意线程安全与类型信息处理,配置 valueSerializer 为 GenericJackson2JsonRedisSerializer。

序列化决定缓存数据如何存储与还原。GenericJackson2JsonRedisSerializer 用 JSON + 类型信息实现可读、跨语言的对象缓存,是 Redis 缓存值序列化的常用方案。

RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
    .entryTtl(Duration.ofMinutes(10))
    .serializeValuesWith(SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
#
★★★

3. CacheManager 的 SPI 在 Redis(Caffeine)+ 多级缓存场景下的实现细节

请说明 CacheManager 的 SPI 在 Redis(Caffeine)+ 多级缓存场景下的实现细节?

  • CacheManager 抽象与 Cache 实现
  • 多级缓存(本地 + 远程)
  • 二级缓存策略与一致性

CacheManager 是 Spring Cache 的抽象,提供 Cache 实例(按名称返回)。Redis 用 RedisCacheManager、Caffeine 用 CaffeineCacheManager。多级缓存场景下,可自定义 CacheManager 与 Cache 实现二级缓存:读时先查本地 Caffeine,未命中再查 Redis,再未命中查 DB 并回填;写时更新两级。实现细节:通常用自定义 Cache 包装 Caffeine 与 Redis,或自定义 CacheManager 根据缓存名返回不同 Cache。一致性是难点:本地缓存即使失效需广播(如 Redis pub/sub 或消息),否则节点间数据不一致;需处理 TTL、缓存穿透/击穿/雪崩。

多级缓存把"本地高速 + 远程共享"结合,CacheManager SPI 提供扩展点。核心难点是本地缓存一致性(失效广播)与击穿/雪崩防护。

#
★★★

4. Spring 7 中 CacheResolver 在动态选择缓存(按租户、按业务线)的工程价值

请说明 Spring 7 中 CacheResolver 在动态选择缓存(按租户、按业务线)的工程价值?

  • CacheResolver 动态决定缓存
  • 按租户/业务线选择不同缓存
  • 与 CacheManager 的配合

CacheResolver 用于在运行时动态解析应使用的缓存(缓存名),Spring Cache 默认使用 SimpleCacheResolver(基于注解的 cacheNames)。自定义 CacheResolver 可按租户、按业务线等动态选择缓存名,例如根据当前租户 ID 返回 "cache:tenant1" 或 "cache:tenant2",实现不同租户/业务线的缓存隔离与策略差异化。工程价值:多租户隔离、不同业务线不同缓存策略(TTL、存储)、灰度发布等。通过 @Cacheable(cacheResolver="...") 指定,与 CacheManager 配合按需解析缓存。

CacheResolver 让"缓存选择"从静态注解变为动态运行时决策,是租户隔离、按业务线差异化缓存的扩展点。

#
★★★

5. Spring Cache 与 Redis 集成(RedisCacheManager)

请说明 Spring Cache 与 Redis 的集成,特别是 RedisCacheManager 的配置?

  • RedisCacheManager 管理 Redis 缓存
  • 配置 TTL、序列化、前缀
  • 缓存名与缓存策略

Spring Cache 与 Redis 集成通过 RedisCacheManager 实现,它管理 Redis 上的 Cache。配置要点:defaultCacheConfig 设置默认 TTL、序列化器(key 用 StringRedisSerializer,value 用 JSON 序列化器)、缓存前缀;为不同缓存名配置不同 TTL(withCacheConfiguration);设置缓存写入/读取策略。RedisCacheManager 是 CacheManager 的 Redis 实现,@Cacheable 等注解通过它读写 Redis 缓存。配置关键在 TTL 与序列化策略,避免数据不可读与过期策略不当。

RedisCacheManager 是"Spring Cache 注解 + Redis 存储"的桥梁。配置 TTL、序列化、前缀是集成核心,保证缓存可读、可控过期。

@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
    RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
        .entryTtl(Duration.ofMinutes(30))
        .serializeKeysWith(SerializationPair.fromSerializer(new StringRedisSerializer()))
        .serializeValuesWith(SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
    return RedisCacheManager.builder(factory).cacheDefaults(config).build();
}
#
★★★

6. Spring Integration 与 Kafka Streams 的整合

请说明 Spring Integration 与 Kafka Streams 的整合方式?

  • Spring Integration 的消息通道
  • Kafka Streams 的流处理
  • 整合与边界

Spring Integration 通过 Spring Integration Kafka 扩展(spring-integration-kafka)与 Kafka 集成:该扩展基于 spring-kafka 的 KafkaTemplate 发送、KafkaMessageListenerContainer 接收,并提供 KafkaProducerMessageHandler(出站)与 KafkaMessageDrivenChannelAdapter(入站)等适配器,将 Kafka 消息接入 Spring Integration 的消息通道(Channel),实现消息驱动的集成。Kafka Streams 是 Kafka 的流处理库,做有状态流处理(聚合、窗口、join)。整合方式:Spring Integration 负责"消息接入/路由",Kafka Streams 负责"流处理",二者可协作——Kafka Streams 处理后的结果输出到 topic,再被 Spring Integration 消费接入业务。边界:Spring Integration 是消息集成框架,Kafka Streams 是流处理引擎,二者关注点不同可互补。

Spring Integration 管"消息集成与路由",Kafka Streams 管"流处理"。整合时前者接入消息、后者处理流,边界清晰、互补增强。

#
★★★

7. Spring Integration 的 Message/Channel/Endpoint 模型

请说明 Spring Integration 的 Message/Channel/Endpoint 模型?

  • Message 消息封装
  • Channel 消息通道
  • Endpoint 端点(Transformer/Filter/Service Activator 等)

Spring Integration 的核心模型包括:Message(消息,封装 payload 与 headers);Channel(消息通道,承载消息的传递,如 DirectChannel、QueueChannel、PublishSubscribeChannel);Endpoint(端点,处理消息的组件,如 Transformer 转换、Filter 过滤、Service Activator 调用服务、Router 路由、Splitter 拆分、Aggregator 聚合)。消息流经 Channel 与 Endpoint 组成集成流,实现企业集成模式(EIP)。通过 @IntegrationComponentScan 或 IntegrationFlow DSL 定义消息流。

Message(数据)、Channel(通道)、Endpoint(处理)构成 Spring Integration 的三要素。理解其协作即理解企业集成模式的基础。

#
★★★

8. Spring Integration 的事务边界

请说明 Spring Integration 的事务边界?

  • 消息处理的事务边界
  • 事务同步与消息配置
  • 与外部事务的配合

Spring Integration 可在消息处理端点配置事务边界,通过 TransactionInterceptor 或 poller 的 transactionManager 配置,使消息处理(如 JDBC 写入)在事务中执行。事务边界通常围绕单个端点(如 Service Activator 的通道处理)或 poller 的轮询批次。Spring Integration 的事务与 Spring 事务合作,可配置 tx 属性使消息处理具备事务性,失败回滚。边界是"事务作用于消息处理链的特定环节",配合事务同步(TransactionSynchronization)在事务提交后发布消息。

Spring Integration 的事务边界是"消息处理环节的事务化",通过事务拦截器与 poller 配置,使消息处理具备原子性。

#
★★

9. @Cacheable/@CachePut/@CacheEvict 的语义差异

请说明 @Cacheable、@CachePut、@CacheEvict 的语义差异?

  • @Cacheable 查询缓存
  • @CachePut 更新缓存
  • @CacheEvict 删除缓存

@Cacheable 用于查询场景:方法调用前先查缓存,命中直接返回缓存值不执行方法,未命中执行方法并将结果写入缓存;@CachePut 用于更新场景:总是执行方法并把返回值写入缓存(不查询缓存);@CacheEvict 用于删除场景:方法执行后(或前)删除指定缓存,清空过期数据。三者语义:Cacheable 读缓存、CachePut 写缓存、CacheEvict 删缓存。组合使用可维护缓存一致性(如 CachePut 更新、CacheEvict 失效)。

三注解对应"读/写/删"三个缓存操作。理解语义差异是正确使用缓存、避免脏数据的关键。

#
★★

10. @Gateway 与 Spring Integration 的服务调用

请说明 @Gateway 注解与 Spring Integration 的服务调用?

  • @Gateway 定义消息网关
  • 网关方法调用映射到消息流
  • 请求/应答模式

@Gateway 注解用于定义消息网关(Messaging Gateway),把接口方法调用映射到 Spring Integration 的消息流。标注了 @Gateway 的接口方法,调用时被转换为消息发送到指定通道,方法的返回值从应答通道接收结果,实现"同步调用 + 消息流"的封装。@Gateway 支持 requestChannel(请求通道)、replyChannel(应答通道)、payloadExpression 等属性。它让业务代码像调用普通方法一样触发消息流,屏蔽消息细节,是 Spring Integration 的服务调用入口。

@Gateway 把"方法调用"桥接到"消息流",实现请求-应答式消息调用。业务代码无需关心消息细节,是集成层的门面。

#
★★

11. Cache.put 与 Cache.evictIfPresent 的工程价值

请说明 Cache.put 与 Cache.evictIfPresent 的工程价值?

  • Cache.put 显式写入缓存
  • Cache.evictIfPresent 条件删除
  • 编程式缓存管理

Cache.put 用于显式向缓存写入数据,Cache.evictIfPresent 用于当缓存中存在该 key 时才删除(相比 evict 更安全,避免误删不存在条目)。二者都属于编程式缓存操作(通过 CacheManager 获取 Cache 后调用),在需要手动控制缓存读写而不依赖注解的场景使用。工程价值:Cache.put 用于显式更新缓存(如异步刷新)、Cache.evictIfPresent 用于条件失效,配合 @CachePut/@CacheEvict 提供更精细的缓存控制。evictIfPresent 是 Spring 6.1 起 Cache 接口新增的默认方法,避免对不存在 key 的操作。

Cache 接口提供编程式缓存操作,put 显式写、evictIfPresent 条件删,是注解之外精细控制缓存的补充手段。

#
★★

12. ClaimCheck 模式与大消息

请说明 ClaimCheck 模式及其在大消息处理中的作用?

  • ClaimCheck 模式(存引用、分离消息体)
  • 大消息处理
  • 减少消息体传输

ClaimCheck 模式(票据检查模式)是一种企业集成模式:消息体较大时,不直接传输完整消息体,而是把消息体存储到外部存储(DB、文件、对象存储),消息中只携带"票据"(check,即存储引用/ID)。接收方凭票据取回消息体。作用是减少大消息在消息通道中的传输开销,避免消息体过大造成的性能与存储问题。Spring Integration 支持 ClaimCheck 模式的实现(通过 Store 与 ClaimCheck 组件)。结合 @Cacheable 等可优化大对象处理。

ClaimCheck 模式是"大消息瘦身"手段——把大负载存外部、消息只传引用,降低传输与存储成本。

#
★★

13. Spring Cache 6.x/7.x 的演进

请说明 Spring Cache 6.x/7.x 的演进?

  • 缓存抽象演进
  • 新特性(Observability、性能)
  • API 变化

Spring Cache 6.x/7.x 的演进:缓存抽象(CacheManager/Cache)保持稳定,但增强了可观测性(Observability,缓存命中/未命中指标)、对 AI 相关缓存(Spring AI)的支持、以及性能优化。Spring 6.1 起 Cache 接口新增细粒度操作(如 evictIfPresent、invalidate),后续版本完善 CacheErrorHandler、增强可观测性与响应式缓存的协作。演进方向是"稳定抽象 + 增强可观测性与新场景支持"。API 层面基本兼容,新增能力按需使用。

Spring Cache 演进是"核心抽象稳定 + 可观测性/AI/性能增强"。核心 CacheManager/Cache 语义不变,新增细粒度与可观测能力。

#
★★

14. Spring Cache 与 Caffeine 集成

请说明 Spring Cache 与 Caffeine 的集成?

  • CaffeineCacheManager
  • Caffeine 配置(maximumSize、expireAfterWrite)
  • 本地缓存

Spring Cache 与 Caffeine 集成通过 CaffeineCacheManager(或自定义 CaffeineCache)实现。Caffeine 是高性能本地缓存库,提供 maximumSize(最大容量)、expireAfterWrite(写后过期)、expireAfterAccess(访问后过期)、refreshAfterWrite(写后刷新)、缓存淘汰与统计。配置方式:CaffeineCacheManager 设置 Caffeine 实例,或通过 Caffeine 构建器配置。适用于本地缓存、单机高频读场景。Caffeine 缓存容量与过期策略控制内存与一致性。

Caffeine 是 Spring Cache 的本地缓存首选,配置容量与过期策略控制内存与数据新鲜度,适合单机高频读。

#
★★

15. Spring Cache 与 JSR-107(JCache)的集成

请说明 Spring Cache 与 JSR-107(JCache)的集成?

  • JSR-107(JCache)标准
  • Spring Cache 与 JCache 的适配
  • JCacheCacheManager

JSR-107(JCache)是 Java 缓存标准 API,定义 CacheManager、Cache、Entry 等通用缓存接口。Spring Cache 与 JSR-107 集成:Spring 提供 JCacheCacheManager(适配 JCache 的 CacheManager),把 JCache 的缓存接入 Spring Cache 抽象,使 @Cacheable 等注解可操作 JCache 缓存。同时 Spring 支持 JCache 注解(@CacheResult 等)或通过 Spring 注解管理 JCache。集成价值是"标准缓存 API + Spring 抽象"的统一,可切换不同 JCache 实现(Ehcache、Caffeine 等)。

JSR-107 是缓存标准,Spring Cache 通过 JCacheCacheManager 适配,使 Spring 注解与标准 JCache 缓存互通,实现可切换。

#
★★

16. Spring Cache 与 Spring Modulith 的边界

请说明 Spring Cache 与 Spring Modulith 的边界?

  • Spring Cache 关注缓存
  • Spring Modulith 关注模块化
  • 两者协同与边界

Spring Cache 与 Spring Modulith 关注维度不同:Spring Cache 关注"数据缓存"(如何缓存、命中、失效),Spring Modulith 关注"模块化架构"(模块边界、事件驱动、模块校验)。边界:Spring Cache 是方法级缓存抽象,Spring Modulith 是架构级模块组织。二者可协同:模块内的缓存注解被 Spring Cache 管理,模块间通过事件协作(缓存失效可通过事件广播)。但要区分职责——缓存是"数据层优化",Modulith 是"架构组织",不要混为一谈。

边界是"缓存(数据层)vs 模块化(架构层)"。Spring Cache 管数据缓存,Modulith 管模块组织,可在模块内缓存并用事件同步失效。

#
★★

17. Spring Cache 失效事件的发布(CacheInvalidationEvent)

请说明 Spring Cache 失效事件的发布(CacheInvalidationEvent)?

  • 缓存失效事件
  • 跨节点缓存同步
  • 事件驱动失效

CacheInvalidationEvent 是 Spring Cache 的缓存失效事件,当缓存被删除/失效时发布,用于实现跨节点缓存同步。在分布式多实例场景,本地缓存失效后通过事件广播通知其他节点,使各节点缓存一致。Spring Cache 结合 Spring 事件机制(ApplicationEventPublisher)发布失效事件,或通过 Redis pub/sub、消息队列广播。工程价值是解决"多实例本地缓存一致性"问题——通过事件驱动各节点同步失效。结合 Spring Modulith 的事件发布可跨模块关联。

缓存失效事件解决"分布式本地缓存一致性"——某节点失效后广播通知其他节点同步失效,避免脏数据。

#
★★

18. Spring Cache 抽象(CacheManager/Cache)的体系

请说明 Spring Cache 抽象(CacheManager/Cache)的体系?

  • CacheManager 管理与创建 Cache
  • Cache 接口操作
  • 各实现(Redis/Caffeine/JCache)

Spring Cache 抽象由 CacheManager 与 Cache 两层组成:CacheManager 负责按名称创建和管理 Cache(如 ConcurrentMapCacheManager、RedisCacheManager、CaffeineCacheManager、JCacheCacheManager);Cache 接口定义缓存操作(get、put、evict、clear、get 带函数)。@Cacheable 等注解通过 CacheManager 获取 Cache 并操作。各实现封装不同的缓存后端(内存、Redis、Caffeine、JCache),但统一暴露 CacheManager/Cache 接口,使缓存后端可切换、注解代码不变。体系体现了"抽象统一、实现可插拔"。

CacheManager(管理)+ Cache(操作)是 Spring Cache 的分层抽象。后端可切换而注解不变,是缓存抽象的核心价值。

#
★★

19. Spring Cache 的 @Cacheable/@CacheEvict/@CachePut 在 Spring Framework 7 中的语义变化与 SpEL 解析边界

请说明 Spring Cache 的 @Cacheable/@CacheEvict/@CachePut 在 Spring Framework 7 中的语义变化与 SpEL 解析边界?

  • 三注解语义在 Spring 7 的稳定与变化
  • SpEL 解析边界
  • 可观测性增强

Spring Framework 7 中 @Cacheable/@CacheEvict/@CachePut 的核心语义保持稳定(读/删/写),变化集中在:可观测性增强(缓存命中/未命中指标)、对 SpEL 解析的边界更严格(更清晰的 SpEL 上下文与错误处理)、Condition 与 unless 的 SpEL 解析优化。SpEL 解析边界:key 的 SpEL 表达式基于方法参数与 context,unless 基于返回值,condition 基于进入方法前;SpEL 无法访问非公开属性,需注意表达式作用域与语法。整体语义稳定,新增能力围绕可观测性与 SpEL 健壮性。

Spring 7 的缓存语义稳定,演进在可观测性与 SpEL 解析健壮性。SpEL 边界决定 key/condition/unless 能访问什么,理解才能正确写表达式。

#
★★

20. Spring Cache 的 CacheErrorHandler 自定义

请说明 Spring Cache 的 CacheErrorHandler 自定义?

  • CacheErrorHandler 处理缓存异常
  • 缓存失败不影响主流程
  • 自定义处理策略

CacheErrorHandler 用于处理缓存操作抛出的异常。默认 SimpleCacheErrorHandler 会把缓存异常抛出,导致业务方法失败;自定义 CacheErrorHandler 可定义缓存异常处理策略(如记录日志、降级忽略),使缓存故障不影响主业务逻辑。通过 CacheConfigurer 或 @EnableCaching 的配置指定 CacheErrorHandler Bean。作用:缓存是可降级的,缓存存储/序列化失败不应中断业务,自定义错误处理提升健壮性(如失败时忽略并继续查询 DB)。

缓存故障不应拖垮业务。CacheErrorHandler 自定义缓存异常的降级策略(记录/忽略),是实现"缓存可用性降级"的关键。

#
★★

21. Spring Integration 6.x 的响应式支持

请说明 Spring Integration 6.x 的响应式支持?

  • 响应式 Channel(ReactiveStreams)
  • 响应式端点
  • 与 Reactor 集成

Spring Integration 6.x 增强了对响应式编程的支持:提供 ReactiveStreamsConsumer(响应式消费者)、响应式 Channel(如 FluxMessageChannel)、响应式适配器,使消息流可基于 Reactor 的 Flux/Mono 处理,支持背压与异步。响应式端点(如响应式 Service Activator)返回 Flux/Mono,订阅执行。Spring Integration 6 与 Project Reactor 深度集成,支持在集成流中使用响应式类型,实现非阻塞消息处理。适合与 WebFlux、响应式中间件结合。

Spring Integration 6 的响应式支持让消息流可基于 Reactor 非阻塞处理,支持背压,是向响应式生态演进的能力。

#
★★

22. Spring Integration 与 Spring Batch 的边界

请说明 Spring Integration 与 Spring Batch 的边界?

  • Spring Integration 消息集成
  • Spring Batch 批处理
  • 边界与协作

Spring Integration 与 Spring Batch 关注点不同:Spring Integration 是消息集成框架(消息、通道、端点、路由),做系统间消息集成与消息驱动;Spring Batch 是批处理框架(Job、Step、Chunk、ItemReader/Writer),做大规模数据处理。边界:Integration 管"消息流与集成",Batch 管"批处理任务"。二者可协作:Spring Integration 接收消息触发 Spring Batch 作业(如监听消息后启动 Job),Batch 处理结果通过 Integration 发布。选择依据:消息集成/路由用 Integration,批量数据处理用 Batch。

边界是"消息集成 vs 批处理"。Integration 管消息流,Batch 管批处理,可协作(消息触发批处理),但职责不同。

#
★★

23. Spring Integration 与 Spring Cloud Stream 的边界

请说明 Spring Integration 与 Spring Cloud Stream 的边界?

  • Spring Integration 消息集成框架
  • Spring Cloud Stream 消息中间件抽象
  • 边界与协同

Spring Integration 是通用的消息集成框架(EIP 模式、通道、端点),Spring Cloud Stream 是构建消息驱动微服务的抽象框架,基于 Spring Integration,提供 binder 抽象(Kafka、RabbitMQ 等)与 @Input/@Output 绑定。边界:Spring Integration 是底层集成框架,Spring Cloud Stream 是基于它的消息驱动微服务抽象,负责"应用与消息中间件"的绑定。Spring Cloud Stream 底层使用 Spring Integration 的通道与绑定机制。选择:微服务消息驱动用 Spring Cloud Stream,通用系统集成用 Spring Integration。

边界是"通用集成框架 vs 消息驱动微服务抽象"。Spring Cloud Stream 构建于 Spring Integration 之上,前者绑定中间件、后者提供底层集成。

#
★★

24. Spring Integration 与 Spring Modulith 事件的关系

请说明 Spring Integration 与 Spring Modulith 事件的关系?

  • Spring Modulith 模块化事件
  • Spring Integration 消息集成
  • 事件与消息的桥接

Spring Modulith 关注模块化架构与模块内事件(ApplicationModuleEvent),Spring Integration 关注消息集成与跨系统消息流。二者关系:Spring Modulith 提供模块化事件发布机制,可结合 Spring Integration 将模块事件转发到外部消息通道(如 Kafka、RabbitMQ),实现"模块内事件 → 跨系统消息"的桥接。Spring Modulith 的 modulith 事件与 Spring Integration 的通道可适配,实现模块化 + 消息集成。边界:Modulith 管模块内事件与边界,Integration 管跨系统消息。

关系是"模块内事件 → 跨系统消息"的桥接。Spring Modulith 提供模块事件,Spring Integration 负责把事件发布到外部消息系统。

#
★★

25. Spring Integration 在 Spring 6.x 的演进

请说明 Spring Integration 在 Spring 6.x 的演进?

  • Spring Integration 6 的基线提升
  • 响应式增强
  • 功能演进

Spring Integration 6(基于 Spring Framework 6)的演进:基线提升到 Java 17 与 Jakarta EE 命名空间;增强响应式支持(ReactiveStreams、响应式 Channel/端点);新增与演变部分适配器(如 Kafka、MQTT、WebSocket);增强可观测性与配置简化(如 Java DSL 更完善)。总体是"基线升级 + 响应式增强 + 现代适配器"。开发者升级时关注包名迁移与响应式 API。

Spring Integration 6 的演进核心是基线升级(Jakarta、Java 17)与响应式能力增强,适配器与 DSL 持续完善。

#
★★

26. Spring Integration 测试支持(@SpringIntegrationTest)

请说明 Spring Integration 的测试支持(@SpringIntegrationTest)?

  • @SpringIntegrationTest 测试注解
  • 消息流测试
  • 测试组件

Spring Integration 提供测试支持,@SpringIntegrationTest 用于集成测试,加载 Spring Integration 上下文并验证消息流。测试方式:通过 MockIntegration 模拟消息发送,验证端点的处理;用 @SpringIntegrationTest 触发消息流,断言消息处理结果、通道内容、端点行为。Spring Integration 测试支持还包括测试 Gateways、poller 等。结合 Spring 测试框架,可验证消息驱动的集成逻辑是否正确。

@SpringIntegrationTest 让消息流可测试,模拟消息输入并断言处理结果,是验证集成逻辑的方法。

#
★★

27. Spring Integration 的监控指标

请说明 Spring Integration 的监控指标?

  • 消息通道统计
  • 端点指标
  • Micrometer 集成

Spring Integration 提供监控指标,通过 Micrometer 集成暴露消息处理的统计信息:通道的发送/接收消息数、处理时间、错误数、队列深度等。通过 actuator 的 /metrics 或 /actuator/integration 端点查看。指标基于 ChannelInterceptor 与端点统计,用于监控消息流性能、积压与故障。结合 MicrometerRegistry 可导出到 Prometheus 等。监控指标帮助定位消息处理瓶颈与异常。

Spring Integration 通过 Micrometer 暴露通道与端点的统计指标,是监控消息流性能与积压的手段。

#
★★

28. @CacheEvict 的 beforeInvocation=true 与 afterInvocation 在方法抛异常时的缓存行为差异

请说明 @CacheEvict 的 beforeInvocation=true 与 afterInvocation(默认)在方法抛异常时的缓存行为差异?

  • beforeInvocation=true 方法执行前删除缓存
  • afterInvocation 方法执行后删除缓存
  • 异常时的行为差异

@CacheEvict 的 beforeInvocation=true 表示在方法执行前删除缓存,afterInvocation=true(默认)表示方法执行后删除。差异在方法抛异常时:beforeInvocation=true 在方法执行前就已删除缓存,即使方法抛异常,缓存也已删除(下次会重新加载);afterInvocation(默认)方法执行后删除,若方法抛异常则不会执行删除,缓存保留。选择:希望方法异常时也缓存失效用 beforeInvocation=true;仅方法成功时失效用默认 afterInvocation。

差异是"异常是否触发缓存删除"。beforeInvocation 删除先于执行(异常也删),afterInvocation 删除后于执行(异常不删)。按业务选择。

#
★★

29. Spring Cache 的 key 生成策略(KeyGenerator/SimpleKey)与 SpEL 自定义 key 的坑

请说明 Spring Cache 的 key 生成策略(KeyGenerator/SimpleKey)与 SpEL 自定义 key 的坑?

  • 默认 SimpleKey 生成
  • KeyGenerator 自定义
  • SpEL 自定义 key 的坑

Spring Cache 的 key 生成:未指定 key 时用 SimpleKeyGenerator 基于方法参数生成 key(SimpleKey.EMPTY、包含所有参数);可自定义 KeyGenerator 实现统一 key 策略;或用 SpEL 表达式自定义 key(如 #id、#user.name)。坑:SpEL 自定义 key 要注意参数名需用 @Param 或开启编译参数(-parameters),否则无法用参数名引用;简单对象直接作 key 需重写 equals/hashCode;key 应简洁稳定,避免把大对象放 key;方法无参数时默认 key 相同,需注意。KeyGenerator 与 SpEL 结合使用需明确优先级。

key 生成决定缓存标识。默认 SimpleKey 基于参数,SpEL 自定义更灵活但需注意参数名编译与对象 equals/hashCode,是常见坑点。

#
★★

30. 缓存预热(启动加载)与异步刷新的实现方式,如何避免缓存雪崩

请说明缓存预热(启动加载)与异步刷新的实现方式,以及如何避免缓存雪崩?

  • 缓存预热(启动加载热点数据)
  • 异步刷新(定时/异步更新缓存)
  • 避免缓存雪崩(TTL 随机、多级、降级)

缓存预热:应用启动时(ApplicationRunner/启动后回调)加载热点数据到缓存,避免首访穿透。异步刷新:通过 @Scheduled 定时或异步任务定期刷新缓存,避免缓存过期后集中回源。避免缓存雪崩:设置 TTL 随机化(避免同一时间大量过期)、多级缓存(本地 + 远程)、缓存降级(失效时走 DB 并限流)、用 sync=true 防击穿。缓存雪崩是"大量缓存同时失效导致 DB 压力暴增",通过 TTL 分散、多级、降级与预热结合防御。

缓存预热解决"冷启动穿透",异步刷新避免"集中过期",随机 TTL/多级/降级防护雪崩。三者结合保障缓存层稳定。

#

31. @Cacheable/@CachePut/@CacheEvict 的语义与组合,缓存击穿/穿透/雪崩如何应对?

请说明 @Cacheable/@CachePut/@CacheEvict 的语义与组合,以及缓存击穿/穿透/雪崩的应对?

  • 三注解语义与组合
  • 缓存击穿/穿透/雪崩
  • 应对策略

@Cacheable 读缓存、@CachePut 写缓存、@CacheEvict 删缓存,组合可维护缓存一致性(如 CachePut 更新、CacheEvict 失效)。缓存问题与应对:击穿(热点 key 失效瞬间并发穿透)用 sync=true 或互斥锁;穿透(查不存在的 key)用空值缓存或布隆过滤器;雪崩(大量 key 同时失效)用 TTL 随机化、多级缓存、降级。三注解语义决定"何时读写删",组合 + 策略应对三类缓存问题。

三注解是缓存操作原语,配合防护策略应对击穿/穿透/雪崩。理解语义与三类问题的成因是缓存设计的核心。

#

32. Spring 消息抽象,JmsTemplate/KafkaTemplate 与 @JmsListener/@KafkaListener 的确认与重试如何?

请说明 Spring 消息抽象:JmsTemplate/KafkaTemplate 与 @JmsListener/@KafkaListener 的确认与重试?

  • JmsTemplate/KafkaTemplate 发送消息
  • @JmsListener/@KafkaListener 消费消息
  • 确认(ack)与重试

Spring 消息抽象统一消息发送与消费:JmsTemplate 发送 JMS 消息、KafkaTemplate 发送 Kafka 消息;@JmsListener/@KafkaListener 监听并消费消息。确认机制:JMS 的 acknowledgeMode(AUTO_CLIENT/DUPS_OK 等)控制消息确认;Kafka 通过 enable.auto.commit 与手动 ack(Acknowledgment.acknowledge())控制消费确认。重试:消费异常时通过 RetryTemplate 或 @Retryable 重试,或配置 listener 的 retry 策略;Kafka 可配置 retry 次数与 backoff,重试失败可转死信队列。理解确认与重试保证消息不丢失、不重复消费。

消息抽象统一 Template(发送)与 Listener(消费)。确认(ack)与重试保障消息可靠投递,需结合中间件配置手动 ack 与重试策略。

#

33. @Cacheable 对方法返回 null 的默认行为(不缓存)与 null 值缓存策略

请说明 @Cacheable 对方法返回 null 的默认行为(不缓存)以及 null 值缓存策略?

  • 返回 null 默认不缓存
  • 缓存穿透问题
  • allowNullValues 配置

@Cacheable 默认:方法返回 null 时不写入缓存(null 不缓存),下次调用仍会执行方法。这导致"查不到的数据"每次穿透到 DB,可能引发缓存穿透。解决:设置 allowNullValues=true,允许缓存 null 值(存空值,避免穿透),或用空对象/占位符缓存。配置 allowNullValues(RedisCacheConfiguration 的 allowNullValues)控制是否允许缓存 null。null 值缓存能防穿透但需注意空值标识与 TTL,避免缓存污染。

默认不缓存 null 是"防污染"但易穿透。allowNullValues=true 缓存空值防穿透,是缓存穿透的常见应对。