提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
在我写代码过程中(本人基础确实。。),使用到Jedis的时候,在在close()之后,发现jedis还能继续调用get()之类的方法(很大的误区,基础不牢地动山摇啊)
提示:以下是本篇文章正文内容,下面案例可供参考
一、Jedis中close()方法?
曾经本人呢以为通过Jedis jedis=new Jedis(host,port)来的Jedis在通过调用close()方法之后是不能够再次进行使用的,假如有同样疑问的小伙伴继续看下去。
二、Jedis中源码分析
1.close()
Jedis中的close()方法
public void close() {
if (this.dataSource != null) {
Pool<Jedis> pool = this.dataSource;
this.dataSource = null;
if (this.isBroken()) {
pool.returnBrokenResource(this);
} else {
pool.returnResource(this);
}
} else {
this.connection.close();
}
}
其中
if (this.dataSource != null) {
Pool<Jedis> pool = this.dataSource;
this.dataSource = null;
if (this.isBroken()) {
pool.returnBrokenResource(this);
} else {
pool.returnResource(this);
}
}
走的是通过连接池创建Jedis的一个close的方式(不是我们今天的重点)
我们的重点是else后面的代码
else {
this.connection.close();
}
在这段代码中,我们可以看到通过new出来的Jedis的关闭走的是Connection的close()方法,
继续下一步,我们点进去关于Connection的close()方法
public void close() {
if (this.memberOf != null) {
ConnectionPool pool = this.memberOf;
this.memberOf = null;
if (this.isBroken()) {
pool.returnBrokenResource(this);
} else {
pool.returnResource(this);
}
} else {
this.disconnect();
}
}
我们还是走的else中的一段代码,进入disconnect()方法,我们可以看到,我们close()现在中的主要做法就是
this.outputStream.flush(); this.socket.close();-----------------------记住这两个操作(重点)
public void disconnect() {
if (this.isConnected()) {
try {
this.outputStream.flush();
this.socket.close();
} catch (IOException var5) {
this.broken = true;
throw new JedisConnectionException(var5);
} finally {
IOUtils.closeQuietly(this.socket);
}
}
}
首先他去调用了isConnected()方法去进行一个判断,我们进入isConnected()方法去看一下
public boolean isConnected() {
return this.socket != null && this.socket.isBound() && !this.socket.isClosed() && this.socket.isConnected() && !this.socket.isInputShutdown() && !this.socket.isOutputShutdown();
}
这目前就是关于Jedis的close()中的一些源码
2.new Jedis(host,port)
代码如下:
public Jedis(String host, int port) {
this.commandObjects = new CommandObjects();
this.db = 0;
this.transaction = null;
this.isInMulti = false;
this.isInWatch = false;
this.pipeline = null;
this.dataSource = null;
this.connection = new Connection(host, port);
}
我们去查看new Connection(host,port)方法
public Connection(String host, int port) {
this(new HostAndPort(host, port));
}
然后继续点进下个方法
public Connection(HostAndPort hostAndPort) {
this((JedisSocketFactory)(new DefaultJedisSocketFactory(hostAndPort)));
}
继续。。
public Connection(JedisSocketFactory socketFactory) {
this.soTimeout = 0;
this.infiniteSoTimeout = 0;
this.broken = false;
this.socketFactory = socketFactory;
}
到了这个时候new Jedis(host,port)的所有操作就做完了
这时候细心的同学就会发现了,在调用close()方法的时候,关于Connection中的close()方法,在上面啊,我再次例举出来,他最终的操作是进行一个socket的close操作
public boolean isConnected() {
return this.socket != null && this.socket.isBound() && !this.socket.isClosed() && this.socket.isConnected() && !this.socket.isInputShutdown() && !this.socket.isOutputShutdown();
}
我们可以发现,在new 的时候并没有给Connection中的socket赋值,此时socket处于null,没有建立连接,所以我们在new Jedis之后直接调用Jedis的close()方法是不去进行任何操作的,那是在什么时候socket所建立连接的呢?
3.Connection的executeCommand(CommandObject<T> commandObject)方法
查看源码的时候我们可以发现在使用Jedis做一些增删改查之类的命令时候,他会调用Connection的executeCommand(CommandObject<T> commandObject)方法
举个栗子
public String set(byte[] key, byte[] value, SetParams params) {
this.checkIsInMultiOrPipeline();
return (String)this.connection.executeCommand(this.commandObjects.set(key, value, params));
}
public byte[] get(byte[] key) {
this.checkIsInMultiOrPipeline();
return (byte[])this.connection.executeCommand(this.commandObjects.get(key));
}
public byte[] getDel(byte[] key) {
this.checkIsInMultiOrPipeline();
return (byte[])this.connection.executeCommand(this.commandObjects.getDel(key));
}
public byte[] getEx(byte[] key, GetExParams params) {
this.checkIsInMultiOrPipeline();
return (byte[])this.connection.executeCommand(this.commandObjects.getEx(key, params));
}
我们现在来看一看Connection的executeCommand(CommandObject<T> commandObject)方法
public <T> T executeCommand(CommandObject<T> commandObject) {
CommandArguments args = commandObject.getArguments();
this.sendCommand(args);
if (!args.isBlocking()) {
return commandObject.getBuilder().build(this.getOne());
} else {
Object var3;
try {
this.setTimeoutInfinite();
var3 = commandObject.getBuilder().build(this.getOne());
} finally {
this.rollbackTimeout();
}
return var3;
}
}
其中我们关于this.sendCommand(args);方法要格外注意,我们点进去
public void sendCommand(CommandArguments args) {
try {
this.connect();
Protocol.sendCommand(this.outputStream, args);
} catch (JedisConnectionException var5) {
JedisConnectionException ex = var5;
try {
String errorMessage = Protocol.readErrorLineIfPossible(this.inputStream);
if (errorMessage != null && errorMessage.length() > 0) {
ex = new JedisConnectionException(errorMessage, ex.getCause());
}
} catch (Exception var4) {
}
this.broken = true;
throw ex;
}
}
这时候this.connect()方法格外的引起了我的注意,我们继续点进去
public void connect() throws JedisConnectionException {
if (!this.isConnected()) {
try {
this.socket = this.socketFactory.createSocket();
this.soTimeout = this.socket.getSoTimeout();
this.outputStream = new RedisOutputStream(this.socket.getOutputStream());
this.inputStream = new RedisInputStream(this.socket.getInputStream());
} catch (JedisConnectionException var6) {
this.broken = true;
throw var6;
} catch (IOException var7) {
this.broken = true;
throw new JedisConnectionException("Failed to create input/output stream", var7);
} finally {
if (this.broken) {
IOUtils.closeQuietly(this.socket);
}
}
}
}
我们可以发现就是在这里建立的连接操作,看到这里,能否明白我们一开始的那个误区呢
总结:
这目前只是我这个小菜鸟的一个见解,麻烦各位大佬指正