摘要: 主要针对Dao层的一些数据库查询的操作,数据实时性不强,直接加入缓存。当缓存中有的时候,就使用缓存中的数据。这样的方法,最终仅仅使用一个注解实现。对于之前的hibernate二级缓存使用,比较陌生。比如是否支持Redis或者可以自己开发支持。是否支持针对部分需要加入缓存的方法配置,而不是所有的hibernate实体都加入缓存。可能我这种方法对于二级缓存来说,抛开代码差距,也是殊途同归的东西。

这几天工作中,突然遇到了对于有些个实体类,需要被缓存起来。但是这些个实体类数目庞大, 初始化加载的话,太耗费时间。所以初步的方案就是先查缓存,缓存没有就查询数据库,查完数据库再放入缓存。同时也方便设置过期时间。

但是针对目前的项目来说,Dao是作为独立的Maven Module,Redis也是独立的Maven Module,相互耦合的话,代码变得难以维护,结构不清晰。所以引入了注解,然后在Redis项目中,针对注解做AOP,这样的话,没有用到缓存的项目,就可以忽略这样的注解。如果用到了,可以自动加入缓存。

注解代码:

package com.ns.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit;
/**
* 只能注解dao里面对应的get方法,传递的参数作为hashkey,返回的值作为value
* @author Han
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Cached {
/**
* redis key
* @return
*/
String key();
/**
* 过期时间,默认为0即永不过期
* @return
*/
long timeout() default 0L;
/**
* 时间单位,默认为秒
* @return
*/
TimeUnit timeunit() default TimeUnit.SECONDS; }

Aop切面代码

package com.ns.redis.aop;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map; import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert; import com.ns.annotation.Cached;
import com.ns.redis.dao.base.BaseRedisDao;
/**
* 对dao的getbean的缓存处理
* @author Han
*/
@Aspect
@Component
public class AutoRedisCached extends BaseRedisDao<String, Object>{ /*
* 约束任意包下的包含Dao的类的任意方法,并且被cached注解
*/
@Pointcut("execution(* *..*Dao*.*(*,..) && @annotation(com.ns.annotation.Cached))")
private void cacheMethod(){} @Around("cacheMethod()")
public Object doArround(ProceedingJoinPoint pjp) throws Throwable{
Object[] args = pjp.getArgs();
//定义序列化器
final RedisSerializer<String> keySerializer = getKeySerializer();
final RedisSerializer<Object> hashValueSerializer = getHashValueSerializer();
final RedisSerializer<Object> hashKeySerializer = getHashKeySerializer(); //序列化参数,作为hashkey
byte [] hashkeyBytesTmp = null;
if(args.length == 1){
hashkeyBytesTmp = hashKeySerializer.serialize(args[0]);
}else{
hashkeyBytesTmp = new byte[0];
for(Object arg : args){
hashkeyBytesTmp = ArrayUtils.addAll(hashkeyBytesTmp, hashKeySerializer.serialize(arg));
}
} final byte [] hashkeyBytes = hashkeyBytesTmp; MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
Method method = methodSignature.getMethod();
final Cached cacheinfo = method.getAnnotation(Cached.class);
Object obj= null; obj = execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
byte [] tmp = connection.hGet(keySerializer.serialize(cacheinfo.key()), hashkeyBytes);
return hashValueSerializer.deserialize(tmp);
}
});
if(obj == null){
final Object objReturn = pjp.proceed();
if(objReturn != null){
execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
return connection.hSet(keySerializer.serialize(cacheinfo.key()), hashkeyBytes,hashValueSerializer.serialize(objReturn));
}
}); if(cacheinfo.timeout()>0){
expire(cacheinfo.key(), cacheinfo.timeout(), cacheinfo.timeunit());
}
}
obj = objReturn;
}
//从dao获取
return obj;
}
}

深入理解Spring Redis的使用 (六)、用Spring Aop 实现注解Dao层的自动Spring Redis缓存的更多相关文章

  1. spring cloud: Hystrix(六):feign的注解@FeignClient:fallbackFactory(类似于断容器)与fallback方法

    fallbackFactory(类似于断容器)与fallback方法 feign的注解@FeignClient:fallbackFactory与fallback方法不能同时使用,这个两个方法其实都类似 ...

  2. 【译】Spring 4 + Hibernate 4 + Mysql + Maven集成例子(注解 + XML)

    前言 译文链接:http://websystique.com/spring/spring4-hibernate4-mysql-maven-integration-example-using-annot ...

  3. Spring框架之使用JdbcTemplate开发Dao层程序

    简介: JdbcTemplate开发dao层程序     由Spring框架给我们提供,Spring提供的很多操作数据源(关系型数据库,二维表格模型,有明确的行和列(mysql/orcal等) 非关系 ...

  4. Junit结合Spring对Dao层进行单元测试

    关于单元测试,上一次就简单的概念和Mock基础做了,参考:http://60.174.249.204:8888/in/modules/article/view.article.php/74 实际开发过 ...

  5. Spring Boot 2.X(六):Spring Boot 集成Redis

    Redis 简介 什么是 Redis Redis 是目前使用的非常广泛的免费开源内存数据库,是一个高性能的 key-value 数据库. Redis 与其他 key-value 缓存(如 Memcac ...

  6. spring boot / cloud (十六) 分布式ID生成服务

    spring boot / cloud (十六) 分布式ID生成服务 在几乎所有的分布式系统或者采用了分库/分表设计的系统中,几乎都会需要生成数据的唯一标识ID的需求, 常规做法,是使用数据库中的自动 ...

  7. Spring详解(六)------AOP 注解

    上一篇博客我们讲解了 AspectJ 框架如何实现 AOP,然后具体的实现方式我们是通过 xml 来进行配置的.xml 方式思路清晰,便于理解,但是书写过于麻烦.这篇博客我们将用 注解 的方式来进行 ...

  8. Spring Boot 学习笔记(六) 整合 RESTful 参数传递

    Spring Boot 学习笔记 源码地址 Spring Boot 学习笔记(一) hello world Spring Boot 学习笔记(二) 整合 log4j2 Spring Boot 学习笔记 ...

  9. [Spring Cloud实战 | 第六篇:Spring Cloud Gateway+Spring Security OAuth2+JWT实现微服务统一认证授权

    一. 前言 本篇实战案例基于 youlai-mall 项目.项目使用的是当前主流和最新版本的技术和解决方案,自己不会太多华丽的言辞去描述,只希望能勾起大家对编程的一点喜欢.所以有兴趣的朋友可以进入 g ...

随机推荐

  1. .net core 使用swagger自动生成接口文档

     前言 swagger是一个api文档自动生动工具,还集成了在线调试. 可以为项目自动生成接口文档, 非常的方便快捷 Swashbuckle.AspNetCore 是一个开源项目,用于生成 ASP.N ...

  2. 网络安装Centos x64 6.10

    1.下载老毛桃PE最新增强版本,然后生成一个可启动U盘. 2.在U盘或移动硬盘中创建一个目录 MYEXT,然后把centos的安装iso放到里面. 3.引导选择从外置ISO进行安装. https:// ...

  3. VMware启动时提示我已移动或我已复制该虚拟机

    参考地址:https://blog.csdn.net/luxiangzhou/article/details/79626113 1.VMware启动时提示“我已移动该虚拟机”或“我已复制该虚拟机”,选 ...

  4. 局域网IP地址

    A类: 10.X.X.X是私有地址(私有地址就是在互联网上不使用,而被用在局域网络中的地址). 127.X.X.X是保留地址,用做循环测试用的. B类: 172.16.0.0---172.31.255 ...

  5. MongoDB数据库发展历程及商业模式

    2007年,Dwight Merriman, Eliot Horowitz和Kevin Ryan成立10gen软件公司,在成立之初,这家的公司目标进军云计算行业,为企业提供云计算服务.在开发云计算产品 ...

  6. Redis持久化persistence

    一.前言 由于Redis的数据都存放在内存中,如果没有配置持久化,redis重启后数据就全丢失了,于是需要开启redis的持久化功能,将数据保存到磁盘上,当redis重启后,可以从磁盘中恢复数据. R ...

  7. centos7系列Cobbler+kickstart全自动装机实战

    配置yum源,以及epel源 [root@crobbler-90111 ~]# cat /etc/yum.repos.d/aliyun.repo [epel] name=ailiyun baseurl ...

  8. Flink解析kafka canal未压平数据为message报错

    canal使用非flatmessage方式获取mysql bin log日志发至kafka比直接发送json效率要高很多,数据发到kafka后需要实时解析为json,这里可以使用strom或者flin ...

  9. [R]R包版本更迭【持续更新】

    由于R版本更迭,网上或旧的教材上的包可能没有在维护,或者被其他包替代. 做一个表记录碰到的一些替代方案.个人向,非完整指南. * mvpart 2014年之后不再更新,R 3.0版本后无法安装, 提示 ...

  10. 记录一次大量CLOSE_WAIT的情况

    近期的项目中,有一个特殊的需求,对于每个客户端程序有若干个机构,对于每个机构有不同的客户端证书,程序间隔一段时间向服务端进行请求,根据请求的成功与否更新各机构的状态(如正常,证书未配置,证书过期等). ...