有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在具有相同自动关闭对象的多个方法中使用trywithresources

我试图模块化我的代码,但它涉及到传递实现AutoCloseable的对象。假设我有两个公共方法foo1和foo2:

public class MyClass {
  public void foo1() {
      // Connection implements AutoCloseable
      try (Connection conn = createConnection()) {
          foo2(conn);
          // is the connection closed or the behavior unpredictable?
          conn.doSomethingElse();
     }
  }

  public void foo2(Connection conn) {
      try (conn) {
          // do something with the Connection
      }
  }
}

我想从foo1调用foo2,但也允许其他类单独使用foo2

public class OtherClass {
    public void doSomething() {
        MyClass myClass = new MyClass();
        myClass.foo2(createConnection());
    }
}

这是否会导致调用foo2后foo1()中的连接关闭?或者我应该把try with resources放在调用方法中(比如OtherClass中的doSomething())吗


共 (2) 个答案

  1. # 1 楼答案

    你的foo1方法在foo2使用后关闭连接。不需要foo2关闭连接,也不应该关闭。这会产生意想不到的副作用。例如,当你在foo1内调用conn.doSomethingElse()时,你会发现它无法工作,因为对foo2的调用已经关闭了连接。这违反了principle of least astonishment,因为方法名没有显示这种副作用

    如果你调用它foo2AndCloseTheConnection,那么你就可以清楚地知道它是做什么的,但是我建议遵循经验法则,创建closeable的方法应该是唯一一个关闭它的方法如果你一直遵循这一点,你就永远不需要查看函数内部,看看你打开的东西是否被该函数关闭。你只需要自己明确地关闭它

    如果希望从其他方法调用foo2,则需要使这些方法关闭连接:

    public void doSomething() {
        MyClass myClass = new MyClass();
        try (Connection connection = createConnection()) {
            myClass.foo2(connection);
        }
    }
    
  2. # 2 楼答案

    是的,foo2关闭连接,因此当控件返回foo1时,连接将无效。没有什么不可预测的

    这是一个很好的规则,用创建它们的代码来关闭它们。但如果能够嵌套这些东西,并让它们共享相同的连接和事务,那将是一件好事。一种解决方案是让这些数据访问方法中的每一种都将连接作为参数接收,并有一个外层来获取连接并确保其关闭

    你基本上是在一次一点地改造Spring。Spring使您能够拥有可以使用相同连接的服务,并允许您控制事务在它们之间传播的方式和方式。这是通过使用AOP来包装对象,其中包含从threadlocal数据结构获取线程当前连接的环绕建议。更容易使用spring(或任何容器)