基于aop的redis自动缓存实现
目的:
对于查询接口所得到的数据,只需要配置注解,就自动存入redis!此后一定时间内,都从redis中获取数据,从而减轻数据库压力。
示例:
package com.itliucheng.biz;
import com.itliucheng.annotation.CacheKey;
import com.itliucheng.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* Created by wangliucheng on 2017/9/14 0014.
*/
@Service
public class DemoAnnotationService {
@Cacheable(expire = 300)
public List<Integer> getList(@CacheKey(key = "anyParameter") String anyParameter) {
List<Integer> list = new ArrayList();
//模拟数据库操作
list.add(1);
list.add(2);
list.add(3);
return list;
}
}
对于getList方法,只需要第一次查询,然后存入redis,以后的300s之内都从redis中获取数据
此示例需要了解注解,不了解的可以先看一下注解 这篇
接下来就是具体的操作过程
学习时只关注技术,所以项目就以简单为例
1.创建maven项目,配置pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itliucheng</groupId>
<artifactId>annotation</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
<spring-framework.version>4.1.5.RELEASE</spring-framework.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- spring aop支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- aspectj支持 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.5</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.32</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
项目的结构基本是这样
2.代码部分
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Cacheable {
int expire() default 0;
}
参数的注解,默认无参
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheKey {
String key() default "";
}
没有配置文件,我们都用注解的形式
@Configuration//声明当前类是一个配置类
@ComponentScan("com.itliucheng.biz")//自动扫描包下面所有@Service @Component @Repository和@Controller的类,并注册为bean
@EnableAspectJAutoProxy//注解开启Spring对AspectJ的支持
public class AopConfig {
}
获取jedis实例
public class JedisClient {
private static class JedisHolder{
private static Jedis jedis = new Jedis("10.0.0.32",6279);
}
private JedisClient(){}
public static Jedis getInstance(){
return JedisHolder.jedis;
}
}
接下来是aop的环绕通知
package com.itliucheng.biz;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.itliucheng.JedisClient;
import com.itliucheng.annotation.CacheKey;
import com.itliucheng.annotation.Cacheable;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
/**
* Created by wangliucheng on 2017/9/14 0014.
*/
@Aspect
@Component
public class CacheAspect {
private static final Jedis jedis = JedisClient.getInstance();
@Around("@annotation(cache)")
public Object cached(ProceedingJoinPoint pjp, Cacheable cache) {
String key = this.getCacheKey(pjp);
String value = jedis.get(key);
if(!StringUtils.isEmpty(value)) {
return this.isJSONArray(value, pjp);
}
Object obj = null;
try {
obj = pjp.proceed();
if(obj == null) {
return obj;
}
value = JSON.toJSONString(obj);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
if(cache.expire() <= 0) {
jedis.set(key, value);
} else {
jedis.setex(key,cache.expire(),value);
}
if(obj instanceof List) {
if(((List)obj).size() > 0) {
Class<?> entityClazz = ((List)obj).toArray()[0].getClass();
return JSONArray.parseArray(value, entityClazz);
}
return JSONArray.parseArray(value);
}
return this.isJSONArray(value, pjp);
}
private Object isJSONArray(String value, ProceedingJoinPoint pjp) {
Object obj = JSONObject.parse(value);
MethodSignature signature = (MethodSignature) pjp.getSignature();
Type type = signature.getMethod().getGenericReturnType();
try {
if (obj instanceof JSONArray) {
if (ParameterizedType.class.isAssignableFrom(type.getClass())) {
Type[] var7 = ((ParameterizedType) type).getActualTypeArguments();
int var8 = var7.length;
byte var9 = 0;
if (var9 < var8) {
Type t1 = var7[var9];
return JSONArray.parseArray(value, (Class) t1);
}
}
return null;
} else {
return JSON.parseObject(value, Class.forName(type.getTypeName()));
}
} catch (ClassNotFoundException | JSONException var11) {
return null;
}
}
private String getCacheKey(ProceedingJoinPoint pjp) {
StringBuilder buf = new StringBuilder();
Signature signature = pjp.getSignature();
String declaringTypeName = signature.getDeclaringTypeName();
String name = signature.getName();
buf.append(declaringTypeName).append(".").append(name);
Object[] args = pjp.getArgs();
Annotation[][] pas = ((MethodSignature)signature).getMethod().getParameterAnnotations();
int length = pas.length;
for(int i = 0; i < length; ++i) {
Annotation[] var1 = pas[i];
int var2 = var1.length;
for(int var3 = 0; var3 < var2; ++var3) {
Annotation an = var1[var3];
if(an instanceof CacheKey) {
buf.append("|").append(((CacheKey)an).key()).append("=").append(args[i].toString());
break;
}
}
}
return buf.toString();
}
}
业务层的某个方法
package com.itliucheng.biz; import com.itliucheng.annotation.CacheKey;
import com.itliucheng.annotation.Cacheable;
import org.springframework.stereotype.Service; import java.util.ArrayList;
import java.util.List; /**
* Created by wangliucheng on 2017/9/14 0014.
*/
@Service
public class DemoAnnotationService {
@Cacheable(expire = 300)
public List<Integer> getList(@CacheKey(key = "anyParameter") String anyParameter) {
List<Integer> list = new ArrayList();
//模拟数据库操作
System.out.println("我在查数据库呢!");
list.add(1);
list.add(2);
list.add(3);
return list;
}
}
最后是main方法
public class test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AopConfig.class);
DemoAnnotationService demoAnnotationService = context.getBean(DemoAnnotationService.class);
List<Integer> abc = demoAnnotationService.getList("abc");
abc.forEach(System.out::println);
}
}
这一套完成之后启动main方法,多次请求发现,300s内只有第一次会打印
我在查数据库呢!123
其余均只打印123
是不是很方便?
基于aop的redis自动缓存实现的更多相关文章
- SpringBoot AOP控制Redis自动缓存和更新
导入redis的jar包 <!-- redis --> <dependency> <groupId>org.springframework.boot</gro ...
- java基于注解的redis自动缓存实现
目的: 对于查询接口所得到的数据,只需要配置注解,就自动存入redis!此后一定时间内,都从redis中获取数据,从而减轻数据库压力. 示例: package com.itliucheng.biz; ...
- 基于AOP和Redis实现对接口调用情况的监控及IP限流
目录 需求描述 概要设计 代码实现 参考资料 需求描述 项目中有许多接口,现在我们需要实现一个功能对接口调用情况进行统计,主要功能如下: 需求一:实现对每个接口,每天的调用次数做记录: 需求二:如果某 ...
- 注解+AOP实现redis遍历缓存
1.注解 package com.yun.smart.annotation; import java.lang.annotation.ElementType; import java.lang.ann ...
- 【docker构建】基于docker搭建redis数据库缓存服务
搭建redis服务 首先拉取镜像==>运行镜像为容器 # 先搜索下redis镜像 [root@VM_0_10_centos wordpress]# docker search redis # 拉 ...
- SpringBoot集成Redis实现缓存处理(Spring AOP实现)
第一章 需求分析 计划在Team的开源项目里加入Redis实现缓存处理,因为业务功能已经实现了一部分,通过写Redis工具类,然后引用,改动量较大,而且不可以实现解耦合,所以想到了Spring框架的A ...
- ssm+redis 如何更简洁的利用自定义注解+AOP实现redis缓存
基于 ssm + maven + redis 使用自定义注解 利用aop基于AspectJ方式 实现redis缓存 如何能更简洁的利用aop实现redis缓存,话不多说,上demo 需求: 数据查询时 ...
- 基于redis分布式缓存实现
Redis的复制功能是完全建立在之前我们讨论过的基 于内存快照的持久化策略基础上的,也就是说无论你的持久化策略选择的是什么,只要用到了Redis的复制功能,就一定会有内存快照发生,那么首先要注意你 的 ...
- 【开源项目系列】如何基于 Spring Cache 实现多级缓存(同时整合本地缓存 Ehcache 和分布式缓存 Redis)
一.缓存 当系统的并发量上来了,如果我们频繁地去访问数据库,那么会使数据库的压力不断增大,在高峰时甚至可以出现数据库崩溃的现象.所以一般我们会使用缓存来解决这个数据库并发访问问题,用户访问进来,会先从 ...
随机推荐
- Amazon面试题
亚马逊面试题: 如下所示的Map中,0代表海水,1代表岛屿,其中每一个岛屿与其八领域的区间的小岛能相连组成岛屿群.写代码,统计Map中岛屿个数. /* Q1. Map [ 0 0 0 0 0 0 0 ...
- php 路径问题
今天迁移网站服务器时,路径出错: 解决办法: 在网站首页根目录 设置define 全局变量 ——根目录: 在涉及目录的地方,统统替换为 根目录:
- PHP中 public、protected 和 privare的区别
权限:public>protected>private public:谁都可以调用 protected:只有自己和派生类可以调用 privare:只有自己可以调用
- jquery.i18n.properties.js hacking
/****************************************************************************** * jquery.i18n.proper ...
- C++中atof函数的实现和atoi的实现
在C++中有两个系统函数可以实现字符串转浮点型和字符串转整形,下面实现一下这两个函数. #include <iostream> #include <string> using ...
- selenium-java,启动谷歌浏览器和火狐浏览器
selenium3.4.0-java,启动谷歌浏览器和火狐浏览器-------------------------------------------------------------------- ...
- Python Qt5 Creator 使用创建项目教程
1.下载Creator 4.2.1 2.点击文件-新建项目-QT-QT designer Form 然后 choose 3. 4.窗口组件选择 5.下一步,然后就可以自己设计了,,, 最后说一下,保存 ...
- 7-4线性分组码的matlab程序
补充一点,关于生成矩阵G和校验矩阵H的关系:生成矩阵G是4*7矩阵,分为两块,前4列组成的4*4矩阵为单位矩阵,后3列组成的4*3矩阵我称它监督矩阵,校验矩阵是3*7矩阵,前4列组成的3*4矩阵是监督 ...
- Hyper-V 手动导入虚机配置实例(转载)
原文转载:http://blog.51cto.com/bobzy/980241 Hyper-V提供了很方便的虚机导入和导出功能.平时假如我们想导出虚机,先选中虚机,然后鼠标右键在出现菜单列表中选中“导 ...
- 多文件的Makefile
Linux下编写一般采用gcc编译工具,但gcc无法满足大量的文件同时编译,这是就用到Makefile,首先先介绍一下gcc GCC编译的四个步骤 1.预处理,生成预编译文件(.文件): Gcc –E ...