Spring Infinispan缓存对象过期时间设置方案咨询(旧版本)
针对你使用的infinispan-spring3和infinispan-client-hotrod 6.4.0.Final-redhat-4版本,从手动操作RemoteCache切换到Spring缓存注解后,要实现类似的过期时间设置,这里有几个适配该旧版本的可行方案:
方案1:在SpringRemoteCacheManager配置中设置全局默认TTL
既然你用的是XML配置的SpringRemoteCacheManager,可以在配置时给它绑定的HotRod客户端设置全局默认的缓存过期时间,对应你之前手动设置的15分钟:
<bean id="springRemoteCacheManager" class="org.infinispan.spring.remote.provider.SpringRemoteCacheManager"> <constructor-arg> <bean class="org.infinispan.client.hotrod.RemoteCacheManager"> <constructor-arg> <bean class="org.infinispan.client.hotrod.configuration.ConfigurationBuilder"> <!-- 配置JDG服务器地址 --> <property name="serverList" value="your-jdg-host:11222"/> <!-- 配置全局缓存过期规则 --> <property name="expiration"> <bean class="org.infinispan.client.hotrod.configuration.ExpirationConfiguration"> <!-- 15分钟转换为毫秒:15*60*1000=900000 --> <property name="lifespan" value="900000"/> </bean> </property> </bean> </constructor-arg> </bean> </constructor-arg> </bean>
这个配置会让所有通过该CacheManager创建的缓存条目,默认都拥有15分钟的存活时间,和你之前手动调用cache.put(key, value, 15, TimeUnit.MINUTES)的效果一致。
方案2:在JDG服务器端为特定缓存配置TTL
如果不同缓存需要不同的过期时间,或者你希望把缓存规则集中在服务器端管理,可以直接修改JDG服务器的配置文件(比如standalone.xml或domain.xml),给指定名称的缓存设置TTL:
<cache-container name="default" default-cache="local"> <!-- 这里以分布式缓存为例,根据你的实际缓存类型调整 --> <distributed-cache name="user-cache" mode="SYNC"> <!-- 设置该缓存的条目过期时间为15分钟 --> <expiration lifespan="900000"/> </distributed-cache> </cache-container>
之后在代码中用@Cacheable(value = "user-cache")时,该缓存下的所有条目就会自动按照服务器端配置的15分钟过期。
方案3:自定义CacheResolver实现动态条目级TTL(适合灵活场景)
如果需要针对不同方法甚至不同条目设置不同的过期时间,这个旧版本的Spring集成没有直接支持注解参数配置TTL,但可以通过自定义CacheResolver结合AOP来实现:
步骤1:定义自定义TTL注解
先创建一个注解,用来标记方法需要的过期时间:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface CacheTimeToLive { long value(); TimeUnit unit() default TimeUnit.MINUTES; }
步骤2:实现自定义CacheResolver
通过这个Resolver,我们可以拿到底层的RemoteCache,并结合注解设置TTL:
public class TtlCustomCacheResolver implements CacheResolver { private final CacheManager cacheManager; public TtlCustomCacheResolver(CacheManager cacheManager) { this.cacheManager = cacheManager; } @Override public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> context) { // 获取当前方法的TTL注解 CacheTimeToLive ttlAnnotation = context.getMethod().getAnnotation(CacheTimeToLive.class); if (ttlAnnotation != null) { long ttlMillis = ttlAnnotation.unit().toMillis(ttlAnnotation.value()); // 遍历当前方法关联的缓存 for (String cacheName : context.getOperation().getCacheNames()) { Cache springCache = cacheManager.getCache(cacheName); if (springCache instanceof SpringRemoteCache) { // 获取原生的RemoteCache实例 RemoteCache<Object, Object> remoteCache = ((SpringRemoteCache) springCache).getNativeCache(); // 如果需要全局修改该缓存的TTL,可设置;如果需要条目级,后续结合AOP拦截put操作 // remoteCache.getConfiguration().expiration().lifespan(ttlMillis); } } } // 返回对应的缓存集合 return context.getOperation().getCacheNames().stream() .map(cacheManager::getCache) .collect(Collectors.toList()); } }
步骤3:配置Spring缓存使用自定义Resolver
在XML中配置缓存注解驱动和自定义Resolver:
<cache:annotation-driven cache-resolver="ttlCustomCacheResolver"/> <bean id="ttlCustomCacheResolver" class="com.yourcompany.cache.TtlCustomCacheResolver"> <constructor-arg ref="springRemoteCacheManager"/> </bean>
步骤4:在业务方法上使用
@Cacheable(value = "order-cache", cacheResolver = "ttlCustomCacheResolver") @CacheTimeToLive(15) public Order getOrder(String orderId) { // 业务逻辑:从DB查询订单 return orderRepository.findById(orderId); }
如果需要更细粒度的条目级TTL,可以额外添加Spring AOP切面,拦截缓存方法的返回结果,手动调用RemoteCache.put(key, value, ttl, unit)来设置,这样就能实现和之前手动操作完全一致的灵活控制。
补充:因为你用的是6.4.x的旧版本,这个版本的Infinispan Spring集成还没有支持新版本中@Cacheable注解直接配置expireAfterWrite的特性,所以上述三个方案是最适配当前环境的选择。优先推荐方案1或2,配置简单且维护成本低。
内容的提问来源于stack exchange,提问作者Priyanka

