实现思路:
1、使用注解@Cacheable的属性 cacheNames 来传输 过期时间,格式:name#expireTime
2、然后由 LocalCacheInit 解析注解,后构建支持过期的缓存管理器 CaffeineCacheManager
3、为需要缓存值的方法添加注解 @Cacheable,unless = "#result==null"表示值为空时不缓存
4、写测试方法,定时查看请求结果是否达到预期
5、启用缓存 @EnableCaching、启用定时@EnableScheduling
定时示例:@Scheduled(cron = "*/1 * * * * *") 每秒一次
添加依赖 pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- localCache -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
注册缓存
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* LocalCacheInit
*
* @Date: 2024-1-12 17:35
* @Author:
* @Version: 1.0
*/
@Slf4j
@Component
@EnableCaching
public class LocalCacheInit implements SmartInitializingSingleton, BeanFactoryAware {
private DefaultListableBeanFactory beanFactory;
@Autowired
CaffeineCacheManager caffeineCacheManager;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (DefaultListableBeanFactory)beanFactory;
}
@Override
public void afterSingletonsInstantiated() {
Map<String, Object> beansWithAnnotation = beanFactory.getBeansWithAnnotation(Component.class);
if(MapUtils.isNotEmpty(beansWithAnnotation)){
for (Object cacheValue : beansWithAnnotation.values()) {
ReflectionUtils.doWithMethods(cacheValue.getClass(), method -> {
ReflectionUtils.makeAccessible(method);
boolean cacheAnnotationPresent = method.isAnnotationPresent(Cacheable.class);
if(cacheAnnotationPresent){
Cacheable cacheable = method.getAnnotation(Cacheable.class);
for (String name : cacheable.cacheNames()) {
Caffeine caffeine = Caffeine.newBuilder().recordStats().initialCapacity(128).maximumSize(10240);
String[] nameExpire = name.split("#");
if (nameExpire.length > 1) {
caffeine.expireAfterWrite(Long.valueOf(nameExpire[1]), TimeUnit.SECONDS);
}
caffeineCacheManager.registerCustomCache(name, caffeine.build());
}
for (String name : cacheable.value()) {
Caffeine caffeine = Caffeine.newBuilder().recordStats().initialCapacity(128).maximumSize(10240);
String[] nameExpire = name.split("#");
if (nameExpire.length > 1) {
caffeine.expireAfterWrite(Long.valueOf(nameExpire[1]), TimeUnit.SECONDS);
}
caffeineCacheManager.registerCustomCache(name, caffeine.build());
}
}
});
}
}
}
}
方法使用缓存
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
/**
* LocalCacheService
*
* @Date: 2024-1-12 11:18
* @Author:
* @Version: 1.0
*/
@Slf4j
@Component
public class LocalCacheService {
@Cacheable(cacheNames = "currentTimeMillis#3", unless = "#result==null")
public long currentTimeMillis(Integer a, String bb) {
long start = System.currentTimeMillis();
this.log.info("LocalCacheService--NoCache--currentTimeMillis()={}", start);
return start;
}
@Cacheable(cacheNames = "currentTimeMillis#6", unless = "#result==null")
public long currentTimeMillis2(Integer a, String bb) {
long start = System.currentTimeMillis();
this.log.info("LocalCacheService--NoCache--currentTimeMillis2()={}", start);
return start;
}
}