自定义Redis分布式缓存starter 并使用@Enablexx 控制缓存功能是否启用
文章图片
1.创建maven项目,添加依赖
项目结构
【SpringBoot|SpringBoot自定义分布式缓存starter 并用@Enablexx 控制缓存功能是否启用】
文章图片
pom.xml
4.0.0
com.sgg
aopCache-spring-boot-start
0.0.1-SNAPSHOT
aopCache-spring-boot-start
aopCache-spring-boot-start 1.8 UTF-8UTF-8
2.3.7.RELEASE
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
2.6.0
org.redisson
redisson
3.15.3
org.springframework.boot
spring-boot-starter-aop
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-configuration-processor
true
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
org.springframework.boot
spring-boot-dependencies
${spring-boot.version}
pom
import
2.自定义注解 1.@EnableGmalllCache 启动功能注解
package com.sgg.aopcache.cache.anno;
import com.sgg.aopcache.cache.selector.AopCacheSelector;
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Import(AopCacheSelector.class)
public @interface EnableGmalllCache {
}
2.@GmalllCache 目标方法缓存注解
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface GmalllCache {String cacheKey() default "";
//支持写表达式String bloomName() default "";
//默认是不用布隆String bloomValue() default "";
//布隆需要判断哪个值的表达式String lockKey() default "";
// 分布式锁值}
3.配置类 1.RedissonProperties 配置信息绑定类
/**
* redisson配置信息
*/
@Data
@ConfigurationProperties("spring.redis")
public class RedissonProperties {private String host = "localhost";
private String addresses = "";
private String password = "";
private String port = "6379";
private int timeout = 3000;
private int connectionPoolSize = 64;
private int connectionMinimumIdleSize=10;
private int pingConnectionInterval = 60000;
public static String ADDRESS_PREFIX = "redis://";
}
2. AopCacheConf 组件配置类
public class AopCacheConf {//需要 redisTemplateredissonClient@Bean
public CacheService cacheService(StringRedisTemplate stringRedisTemplate,RedissonClient redissonClient)
{
if (StringUtils.isEmpty(redissonClient)){
throw new RuntimeException("请往容器中添加RedissonClient组件");
}
System.out.println("cacheService方法执行了,往容器中添加CacheService组件");
return new CacheServiceImpl(stringRedisTemplate,redissonClient);
}@Bean
public GmallCacheAspect gmallCacheAspect(CacheService cacheService)
{
System.out.println("GmallCacheAspect方法执行了,往容器中添加GmallCacheAspect组件");
return new GmallCacheAspect(cacheService);
}}
3.RedissonAotoConfiguration 自动装配类
@EnableConfigurationProperties(RedissonProperties.class)
public class RedissonAotoConfiguration {/**
* 自动装配
*
*/@Bean
RedissonClient redissonClient(RedissonProperties redissonConfig) {
Config config = new Config();
if(StringUtils.isEmpty(redissonConfig.getHost())){
throw new RuntimeException("host isempty");
}
SingleServerConfig serverConfig = config.useSingleServer()
.setAddress(RedissonProperties.ADDRESS_PREFIX + redissonConfig.getHost() + ":" +redissonConfig.getPort())
.setTimeout(redissonConfig.getTimeout())
.setPingConnectionInterval(redissonConfig.getPingConnectionInterval())
.setConnectionPoolSize(redissonConfig.getConnectionPoolSize())
.setConnectionMinimumIdleSize(redissonConfig.getConnectionMinimumIdleSize())
;
if(!StringUtils.isEmpty(redissonConfig.getPassword())) {
serverConfig.setPassword(redissonConfig.getPassword());
}
// RedissonClient redisson = Redisson.create(config);
System.out.println("RedissonClient组件创建完成");
return Redisson.create(config);
}}
4.Selector
/**
* @author sz
* @DATE 2022/3/1317:54
*/
public class AopCacheSelector implements ImportSelector {public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//要添加的组件的全限定类名
System.out.println("selectImports方法执行了,往容器中添加AopCacheConf组件");
return new String[]{"com.sgg.aopcache.cache.conf.AopCacheConf"};
}
}
5.切面类
@Slf4j
@Aspect
public class GmallCacheAspect {//没抢到默认的等待时间
private AtomicLong atomicLong = new AtomicLong(1000);
private CacheService cacheService;
public GmallCacheAspect(CacheService cacheService) {
this.cacheService = cacheService;
}public GmallCacheAspect() {}@Around("@annotation(com.sgg.aopcache.cache.anno.GmalllCache)")
public Object around(ProceedingJoinPoint joinPoint) throws Exception {
//先拿到目标方法执行的参数
Object[] args = joinPoint.getArgs();
//拿到方法声明
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//拿到方法声明上注解
Method method = signature.getMethod();
//获取方法方法的返回值类型
final Type returnType = method.getGenericReturnType();
GmalllCache cacheAnnotation = method.getAnnotation(GmalllCache.class);
//拿到注解上的值缓存数据的key
String cacheKeyExpr = cacheAnnotation.cacheKey();
String bloomValueExpr = cacheAnnotation.bloomValue();
//Sp EL表达式 解析
String cacheKey = parseSpel(cacheKeyExpr, joinPoint,"cacheKey");
Long bloomValue=https://www.it610.com/article/null;
if (!StringUtils.isEmpty(bloomValueExpr)){
String bloomVlaueStr = parseSpel(bloomValueExpr, joinPoint,"bloomValue");
bloomValue = https://www.it610.com/article/Long.valueOf(bloomVlaueStr);
}while (true){
//从缓冲中拿数据并根据方法的返回值类型封装数据
Object dataFromCache = cacheService.getDataFromCache(cacheKey, new TypeReference
6.CacheService CacheService接口
public interface CacheService {/**
* 从缓冲中获取数据
* @param spelValue
* @param typeReference
* @return
*/
T getDataFromCache(String spelValue, TypeReference typeReference) throws Exception;
/**
* 获取布隆过滤器名
* @param bloomName
*/
RBloomFilter getBloomFilter(String bloomName);
/**
* 获取一把分布式锁
* @param lockKey
* @return
*/
RLock getLock(String lockKey);
/**
* 将数据存入缓存
* @param cacheKey
* @param detail
* @param returnType
*/
void saveCacheData(String cacheKey, Object detail, Type returnType) throws Exception;
}
CacheServiceImpl 实现类
/**
* @author sz
* @DATE 2022/3/1313:29
*/
public class CacheServiceImpl implements CacheService {StringRedisTemplate redisTemplate;
//操作redisRedissonClient redissonClient;
//使用redissonObjectMapper objectMapper = new ObjectMapper();
public CacheServiceImpl(StringRedisTemplate redisTemplate, RedissonClient redissonClient) {
this.redisTemplate = redisTemplate;
this.redissonClient = redissonClient;
}/**
* 从缓冲获取数据
*
* @param spelValue
* @param returnType
* @return
*/
public T getDataFromCache(String spelValue, TypeReference returnType) throws Exception {
String json = redisTemplate.opsForValue().get(spelValue);
if (StringUtils.isEmpty(json)) {
return null;
}T value = https://www.it610.com/article/objectMapper.readValue(json, returnType);
return value;
}/**
* 获取布隆过滤器
*
* @param bloomName
*/
public RBloomFilter getBloomFilter(String bloomName) {
RBloomFilter
推荐阅读
- Redis|缓存穿透 缓存击穿 缓存雪崩 这三者是什么 如何处理
- linux|Linux 安装项目软件 MySql Redis Nginx RabbitMQ Docker 轻松 详细
- Java|Java面试突击系列(十二)(数据库分库分表的面试连环炮)
- redis|Reids解决海量重复提交问题
- 数据库|redis的常见问题总结
- 数据库|springboot 配置Druid多数据源监控
- springsecurity|SpringBoot整合SpringSecurity带图片验证码简单实现
- java|SpringBoot从入门到入门学习笔记
- MyBatis|Spring Boot(十)(Druid的监控统计和多数据源配置)