目的:

对于查询接口所得到的数据,只需要配置注解,就自动存入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

只贴出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内只有第一次会打印

  1. 我在查数据库呢!
  2. 1
  3. 2
  4. 3

其余均只打印123

是不是很方便?

java基于注解的redis自动缓存实现的更多相关文章

  1. 基于aop的redis自动缓存实现

    目的: 对于查询接口所得到的数据,只需要配置注解,就自动存入redis!此后一定时间内,都从redis中获取数据,从而减轻数据库压力. 示例: package com.itliucheng.biz; ...

  2. SpringMVC + ehcache( ehcache-spring-annotations)基于注解的服务器端数据缓存

    背景 声明,如果你不关心java缓存解决方案的全貌,只是急着解决问题,请略过背景部分. 在互联网应用中,由于并发量比传统的企业级应用会高出很多,所以处理大并发的问题就显得尤为重要.在硬件资源一定的情况 ...

  3. Java基于注解和反射导入导出Excel

    代码地址如下:http://www.demodashi.com/demo/11995.html 1. 构建项目 使用Spring Boot快速构建一个Web工程,并导入与操作Excel相关的POI包以 ...

  4. Spring+Mybatis基于注解整合Redis

    基于这段时间折腾redis遇到了各种问题,想着整理一下.本文主要介绍基于Spring+Mybatis以注解的形式整合Redis.废话少说,进入正题. 首先准备Redis,我下的是Windows版,下载 ...

  5. SpringBoot AOP控制Redis自动缓存和更新

    导入redis的jar包 <!-- redis --> <dependency> <groupId>org.springframework.boot</gro ...

  6. Mybatis基于注解开启使用二级缓存

    关于Mybatis的一级缓存和二级缓存的概念以及理解可以参照前面文章的介绍.前文连接:https://www.cnblogs.com/hopeofthevillage/p/11427438.html, ...

  7. Java中如何使用Redis做缓存

    基本功能测试 1.程序基本结构 2.主要类 1)功能类 package com.redis; import java.util.ArrayList; import java.util.Iterator ...

  8. 基于注解处理器开发自动生成getter和setter方法的插件

    昨天无意中,逛到了lombok的网站,并看到了首页的5分钟视频,视频中的作者只是在实体类中写了几个字段,就可以自动编译为含setter.getter.toString()等方法的class文件.看着挺 ...

  9. java集成memcached、redis防止缓存穿透

    下载相关jar,安装Memcached,安装教程:http://www.runoob.com/memcached/memcached-install.html spring配置memcached &l ...

随机推荐

  1. CentOS 7 安装Subversion, 并用Nginx代理

    环境:CentOS 7.3.1611 分三步:第一步:安装subversion第二步:安装httpd第三步:安装nginx 操作步骤: 安装subversion, 命令 -> yum -y in ...

  2. 在 overlay 中运行容器 - 每天5分钟玩转 Docker 容器技术(51)

    上一节我们创建了 overlay 网络 ov_net1,今天将运行一个 busybox 容器并连接到 ov_net1: 查看容器的网络配置: bbox1 有两个网络接口 eth0 和 eth1.eth ...

  3. 有关cxf与安卓客户端或者C客户端的中文乱码问题

    前段时间在与C的客户端和安卓的客户端进行联调,首先我的方法接收的是C客户端所传递的数据,但是传递到方法内的中文就变成了乱码(我的方法的编码是utf8),最后通过String a = new Strin ...

  4. 阿里消息队列中间件 RocketMQ 源码分析 —— Message 拉取与消费(上)

  5. Can not issue data manipulation statements with executeQuery().解决的方法

    query是查询用的,而update是插入和更新,删除修改用的. executeQuery()语句是用于产生单个结果集的语句,如select语句,在什么情况下用,当你的数据库已经保存了数据后,要进行查 ...

  6. get post请求

    GET 从指定的资源请求数据 /test/demo_form.asp?name1=value1&name2=value2 请求可被缓存 请求保留在浏览器历史记录中 请求可被收藏为书签 请求不应 ...

  7. 【性能测试工具】- Siege

    优点:比http_load好用,因为相同的url.txt文件在httpload不好使,所以在易用性上httpload不如siege,仍需进一步调研. 缺点:安装过程中,不能自动创建siege.log文 ...

  8. 【NO.3-2】Jmeter - 在Linux配置HOSTS的方法

    在Linux配置HOSTS 咱平时在Windows系统做web测试的时候需要修改HOSTS文件.Linux也一样. /*在Linux执行性能测试的时候,很容易忘记配置HOSTS,那么你发送的请求的响应 ...

  9. Ubuntu 16.04 + CUDA 8.0 + cuDNN v5.1 + TensorFlow(GPU support)安装配置详解

    随着图像识别和深度学习领域的迅猛发展,GPU时代即将来临.由于GPU处理深度学习算法的高效性,使得配置一台搭载有GPU的服务器变得尤为必要. 本文主要介绍在Ubuntu 16.04环境下如何配置Ten ...

  10. XSS编码初析

    首先我们应当了解,当我们发送一个请求链接时,服务器与客户端都发生了什么 这里仅涉及到js的编码问题,因此就编码来说,首先我们确定我们发出的请求是采用GET的方式还是采用POST的方式 若采用GET的方 ...