有关Jedis中close()方法的误区

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

在我写代码过程中(本人基础确实。。),使用到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);
                }

            }
        }

    }

我们可以发现就是在这里建立的连接操作,看到这里,能否明白我们一开始的那个误区呢

总结:

 这目前只是我这个小菜鸟的一个见解,麻烦各位大佬指正

 

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值