java中使用redis总是需要处理redis连接的获取,释放等操作,每次使用都会使代码变的特别丑陋,模仿spring中aop的实现,用动态代理写一个 连接自动获取和释放的工具
主要思路
JedisManageSupport 抽象类 类似于 aop的切入点,所有继承了该类(一般都是service层)的类,可以使用提供的获取redis的方法获取redis,并且不需要释放
JedisBeanPostProcessor 继承BeanPostProcessor ,会在bean初始化时执行自己定义的逻辑:
如果A类继承了 JedisManageSupport ,就会获取redis连接并且放到JedisManageSupport 的成员变量里,A类的实例(其实是cglib动态代理生成的
A类的子类的实例)就可以使用该redis连接 进行相关操作了
代理类的实例见源码
源码如下
public class JedisBeanPostProcessor implements BeanPostProcessor {
@Autowired
ShardedJedisPool shardedJedisPool;
static final Logger logger = Logger.getLogger(JedisBeanPostProcessor.class);
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof JedisManageSupport) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(bean.getClass());
enhancer.setCallback(new JedisInterceptor(shardedJedisPool, bean));
Object targetBean = enhancer.create();
return targetBean;
}
else {
return bean;
}
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
class JedisInterceptor implements MethodInterceptor {
static final Logger logger = Logger.getLogger(JedisInterceptor.class);
ShardedJedisPool pool;
Object src;
public JedisInterceptor(ShardedJedisPool pool, Object src) {
this.pool = pool;
this.src = src;
}
@Override
public Object intercept(Object target, Method method, Object[] arguments, MethodProxy methodProxy) throws Throwable {
Object result = null;
if (target instanceof JedisManageSupport) {
if (this.isDeclaredMethod(target, method)) {
ShardedJedis jedis = null;
try {
JedisManageSupport support = (JedisManageSupport) src;
jedis = pool.getResource();
support.setShardedJedis(jedis);
// logger.debug("调用之前注入jedis对象,method:" + method);
/**
* 下面代码可以使用 method.invoke(src,arguments)。 不能使用
* methodProxy.invokeSuper(target,arguments);
* 因为A类中用Autowired注入的属性,生成代理的子类B后,因为子类B是新建的类。从父类继承的属性没有被初始化,
* 使用methodProxy.invokeSuper()执行是,会报空指针异常.
*/
result = methodProxy.invoke(src, arguments);
support.setShardedJedis(null);
}
catch (Exception e) {
pool.returnBrokenResource(jedis);
e.printStackTrace();
}
finally {
if (jedis != null) {
pool.returnResource(jedis);
}
// logger.debug("调用之后归还jedis对象,method:" + method);
}
}
else {
result = methodProxy.invoke(src, arguments);
}
}
else {
throw new Exception("使用该代理必须继承JedisManageSupport");
}
return result;
}
/**
* 是否是target类本身定义的非私有的方法,还是继承的父类
* @return true是target自己类的并且不是私有的的,
*/
private boolean isDeclaredMethod(Object target, Method arg1) {
Method temp = null;
try {
temp = target.getClass().getDeclaredMethod(arg1.getName(), arg1.getParameterTypes());
}
catch (SecurityException e) {
e.printStackTrace();
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
/**
* 不为null,并且是非私有的,返回true
*/
if (temp != null) {
return true;
}
else {
return false;
}
}
}
public abstract class JedisManageSupport {
ThreadLocal<ShardedJedis> jedisHolder = new ThreadLocal<ShardedJedis>();
public final ShardedJedis getShardedJedis() {
return jedisHolder.get();
}
public final void setShardedJedis(ShardedJedis jedis) {
jedisHolder.set(jedis);
}
/**
* 如果某个键不同单位之间也不会重复,可以使用这个方法生成redis的键
*/
public final byte[] assemKey(String baseKey) {
Assert.isTrue(StringUtils.isNotBlank(baseKey), "参数不能为空");
return baseKey.getBytes();
}
/**
* 根据tableName+prefix 构造唯一key与assemKey(String baseKey, String tableName)
* 规则一致
*/
public final byte[] assemKeyByPrefix(String tableName, String baseKey) {
Assert.isTrue(StringUtils.isNotBlank(baseKey), "参数不能为空");
Assert.isTrue(StringUtils.isNotBlank(tableName), "参数不能为空");
UnitInfo unit = WebService.getUnitInfo();
Assert.isTrue(unit != null, "单位信息获取不到");
return (tableName + "-" + unit.getPrefix() + "-" + baseKey).getBytes();
}
/**
*
* 不同前缀的表中可能有相同的键,同一个表中也可能是有重复的baseKey时,用这个生成redis的key 比如 用户信息表的
* username字段,不同的用户信息表允许重复的username,mooc_t_userinfo
* 也允许有相同的账号,所以生成redis的key时,需要用到单位的mooc_school 放入redis中
*/
public final byte[] assemKeyByFid(String tableName, String baseKey) {
UnitInfo unit = WebService.getUnitInfo();
Assert.isTrue(unit != null, "单位信息获取不到");
return (tableName + "-" + unit.getMoocSchool() + "-" + baseKey).getBytes();
}
}
分享到:
相关推荐
Java EE互联网轻量级框架整合开发 SSM框架(Spring MVC+Spring+MyBatis)和Redis实现
三个核心包,两个依赖包
基础框架:Spring Boot 2.1.0.RELEASE 持久层框架:Spring boot Jpa 安全框架:Spring Security 缓存框架:Redis 日志打印:logback+log4jdbc 接口文档 swagger2 其他:fastjson,aop,MapStruct等。 页面框架:Vue ...
后端使用SpringBoot框架进行业务逻辑开发,利用Spring Security实现权限控制。数据库采用MySQL进行数据存储,使用MyBatis进行数据访问。 权限控制模块设计包括用户、角色和权限三个主要模块。用户模块用于管理用户...
springmvc 的平台架构框架。开发环境 eclipse + maven ,插件lombok, 嵌入了redis
主要实现技术:Java、springmvc、springboot、mybatis、mysql、tomcat、shiro权限框架、vue、jquery、node.js 、redis数据库、邮箱相关等技术。 主要功能实现: 用户登录、注册、商城浏览、购买、订单、购物车、退货...
Smart Shop是一款基于 Spring Cloud +MybatisPlus+XXL-JOB+redis+Vue的前后端分离、分布式、微服务架构的Java商城系统,采用稳定框架开发及优化核心,减少依赖,具备出色的执行效率,扩展性、稳定性高,H5/小程序/...
在面试中,可能会涉及到如何使用Java客户端连接Redis服务器,如何进行数据的读写、删除、更新等操作,以及如何处理Redis的连接池和异常情况等问题。此外,面试官还可能会问到如何与Spring框架集成使用Redis等问题。...
基于注解的spring redis框架
但是该套实现,代码质量非常差(10几个java文件,都快吓晕),并且redis的连接没有基于spring,而是在java代码中硬编码,这几乎无法容忍。 为此,本人基于spring连接redis,吸取了他们文章的思想,重新写了一套解决...
Java基于Redis实现附近的人Demo,框架由Spring-boot实现,压缩包含源码以及部署jar包。代码清晰,有注释,考虑性能优化
本次课程以SpringData为中心,重点讲解了其JPA组件,扩展讲解了redis,mongDB,ES组件,并且对部分组件做了必要的源码分析。而且在课程的最后部分加入了一个综合案例,可以将前面章节所学知识点应用到一个项目中,帮助...
本项目集成了springboot+security+mybatis+redis+jwt用于学习security鉴权功能,其中有集成了redis,mybatis,jasypt,jwt,thymeleaf,knife4j,mybatis-plus 项目搭建已经比较成熟,能够直接进行使用,通过代码...
Java架构面试资料合集Spring面试专题及答案MySQL面试Redis面试资料: BAT面试常问80题 Dubbo服务框架面试专题及答案整理文档 java筑基(基础)面试专题系列(一):Tomcat+Mysql+设计模式 java筑基(基础)面试专题...
包含Java说明文件、配置代码、redis相应版本的Jar 1、代码片段要求的框架为:SpringMVC,但原理都是一样的,采用其他方式也可以。 2、RedisMng为简单封装的接口,不封装,直接采用redisTemplate也可以。
前后端基于json进行交互,接口通过JWT无状态token进行权限校验,使用redis或者数据库进行token缓存,接口完全采用Restful的风格,实现按钮级权限控制,可以作为开发项目的脚手架,做为基础项目。 该版本为mybatis版...
Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是简化新 Spring 应用的初始搭建以及开发过程 Java 开发领域中,有很多著名框架都是 Pivotal 团队的产品,如:Spring 框架及其衍生框架、缓存 Redis 、消息...
spring框架 springmvc框架 mybatis框架 Logback日志框架 安全验证框架 maven框架 layui前端框架 shiro安全框架 系统关键性技术 基于角色的权限访问控制RBCA(Role-BasedAccessControl) Spring+Springmvc+Myb
Java springBlade微服务开发平台 是一个由商业级项目升级优化而来的微服务架构,采用Spring Boot 2.6 、Spring Clou,用前后端分离的模式,前端开源两个框架:Sword (基于 React、Ant Design)、Saber (基于 Vue、...
基于maven的Java web项目框架模板,使用spring + spring_mvc + mybatis + spring-data-redis等框架各种配置文件都已写好的并实现了一个简单的登陆注册功能可用于在IDEA上快速构建网络项目或入门学习 更多spring_mvc...