java使用redis一般都是通过redis.clients.jedis.Jedis来连接redis服务器,通过redis.clients.jedis.Jedis提供的方法使用redis
但是每次执行完jedis里面的方法之后必须关闭链接,释放资源,否则链接一旦用完下次再使用redis程序会堵塞,但是手动关闭链接或出现很多的重复代码,并且有些时候也会忘记关闭
解决方法就是使用代理模式来解决这一问题
代理有两种:java的Proxy类和Spring的Enhancer
区别就是前者只能代理基于接口的类,也就是说代理的类必须是接口,否则无法代理
后者是Spring的代理类,弥补java的Proxy只能代理接口的缺陷
Enhancer使用非常简单,只要使用了Spring就会有,全类目是org.springframework.cglib.proxy.Enhancer
package com.xiaogang.report.proxy;
import com.xiaogang.report.handler.JedisHandler;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
/**
* jedis代理,自动关闭jedis连接
*/
public class JedisProxy {
private JedisPool jedisPool;
public JedisProxy(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
public Jedis createProxy() throws Exception{
Enhancer enhancer = new Enhancer();
//设置代理的父类,就设置需要代理的类
enhancer.setSuperclass(Jedis.class);
//设置自定义的代理方法
Callback callback = new JedisHandler(jedisPool);
enhancer.setCallback(callback);
Object o = enhancer.create();
Jedis jedis = null;
if (o instanceof Jedis){
jedis = (Jedis) o;
}
return jedis;
}
}
package com.xiaogang.report.handler;
import org.springframework.cglib.proxy.InvocationHandler;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import java.lang.reflect.Method;
/**
* jedis代理,自动关闭资源
*/
public class JedisHandler implements InvocationHandler {
private JedisPool jedisPool;
public JedisHandler(JedisPool jedisPool){
this.jedisPool = jedisPool;
}
/**
* 当使用jedis方法的时候,实际调用的这里的方法
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JedisHandler.invoke -----start");
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
Object invoke = method.invoke(jedis, args);
System.out.println("代理方法获得的结果:"+invoke);
return invoke;
}finally {
if (jedis != null) {
jedis.close();
System.out.println("关闭jedis连接");
}
System.out.println("JedisHandler.invoke -----end");
}
}
}
以后获取Jedis对象通过new JedisProxy().createProxy(),使用jedis的方法都会自动关闭连接了
执行结果
JedisHandler.invoke -----start
代理方法获得的结果:redis.clients.util.JedisByteHashMap@ebe4043
关闭jedis连接
JedisHandler.invoke -----end
评论里面说的对,多线程情况下会创建很多代理类,效率不高,会有性能的问题。可以使用连接池的设计思路来进行改造。
当然了,使用spirng data redis更方便,就不用这个设计了