java spring框架中方法级redis的连接自动获取和释放实现

标签: java spring 框架 | 发表时间:2015-08-27 11:19 | 作者:IT少年
出处:http://www.iteye.com
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();
}

}

已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [java spring 框架] 推荐:

java spring框架中方法级redis的连接自动获取和释放实现

- - Java - 编程语言 - ITeye博客
java中使用redis总是需要处理redis连接的获取,释放等操作,每次使用都会使代码变的特别丑陋,模仿spring中aop的实现,用动态代理写一个 连接自动获取和释放的工具. JedisManageSupport 抽象类 类似于 aop的切入点,所有继承了该类(一般都是service层)的类,可以使用提供的获取redis的方法获取redis,并且不需要释放.

Spring 4.1与Java 8 java.util.Optional

- - ImportNew
在Spring 4.1中,利用Java 8的 java.util.Optional,通过 @RequestParam、 @RequestHeader和 @MatrixVariable三个注解,支持了仅包含非空(non-null)的容器对象. 有了Java 8的 java.util.Optional,你可以保证你的参数永远不会为 null.

Spring Boot 中使用 Java API 调用 lucene

- - SegmentFault 最新的文章
Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言). Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎.

微服务框架Spring Cloud介绍 Part2: Spring Cloud与微服务

- - skaka的博客
之前介绍过 微服务的概念与Finagle框架, 这个系列介绍Spring Cloud.. Spring Cloud还是一个相对较新的框架, 今年(2016)才推出1.0的release版本. 虽然Spring Cloud时间最短, 但是相比我之前用过的Dubbo和Finagle, Spring Cloud提供的功能最齐全..

Spring框架学习【基础知识】

- - CSDN博客推荐文章
1.在java开发领域,Spring相对于EJB来说是一种轻量级的,非侵入性的Java开发框架,曾经有两本很畅销的书《Expert one-on-one J2EE Design and Development》和《Expert one-on-one J2EEdevelopment without EJB》是java高手进阶必看的宝典,Spring就是从这两本书的理论发展起来的.

JAVA RPC 通讯框架

- - 经验沉淀 知识结晶
Bison 是一个JAVA 程间的通信框架,基于apache mina 实现,对mina进行了byteBuffer 缓冲区重用以及半包出处时减少拷贝. 客户端(bison-client) 功能点. 2 支持高用性:高可用的一个基本原则,可以接受快速的失败,但不能接受长时间的等待. Githup地址:https://github.com/gavenpeng/Bison.

Java中如何获取Spring中配置的bean

- - CSDN博客推荐文章
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架. 二、如何在程序中获取Spring配置的bean呢. 方法一:在初始化时保存ApplicationContext对象. 说明:这种方式适用于采用Spring框架的独立应用程序,需要程序通过配置文件手工初始化Spring的情况.

[Java][web]利用Spring随时随地获得Request和Session

- - CSDN博客推荐文章
利用Spring随时随地获得Request和Session. 在web.xml中添加  . 1、方法一:通过代码实现. 2、方法二:通过注解实现:. 三、关于RequestContextListener的背景知识:. 基于LocalThread将HTTP request对象绑定到为该请求提供服务的线程上.

使用Java注解进行Spring bean管理

- - 编程语言 - ITeye博客
原文链接: http://www.ibm.com/developerworks/cn/webservices/ws-springjava/. 使用 Java 配置进行 Spring bean 管理. 学习使用 Java 配置管理 Spring bean. Spring bean 是使用传统的 XML 方法配置的.

使用SPRING中的线程池ThreadPoolTaskExecutor实现JAVA并发

- - Java - 编程语言 - ITeye博客
//线程池所使用的缓冲队列 . //线程池维护线程的最少数量 . //线程池维护线程的最大数量 . //线程池维护线程所允许的空闲时间 .  .      .      .      .