Java 在具有相同自动关闭对象的多个方法中使用try with resources

Java 在具有相同自动关闭对象的多个方法中使用try with resources,java,Java,我试图模块化我的代码,但它涉及到传递实现AutoCloseable的对象。假设我有两个公共方法foo1和foo2: public class MyClass { public void foo1() { // Connection implements AutoCloseable try (Connection conn = createConnection()) { foo2(conn); // is the connecti

我试图模块化我的代码,但它涉及到传递实现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())

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

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


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

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

如果您调用它
foo2并关闭连接
,那么您就可以明确它的作用,但我建议遵循经验法则创建可关闭对象的方法应该是唯一关闭它的方法。如果您始终遵循这一点,您永远不需要查看函数内部,以查看您打开的内容是否被该函数关闭。您只需自己显式地关闭它

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

public void doSomething() {
    MyClass myClass = new MyClass();
    try (Connection connection = createConnection()) {
        myClass.foo2(connection);
    }
}

对于
try。。最后
,在
最后
中调用
关闭
。因此,是的,在调用
foo2
之后,它将被关闭。很抱歉,foo2甚至可以编译吗?我的IDE当然不允许我这样做。据我在语言规范中看到的,try with resources需要在大括号中声明一个新的变量。您能详细介绍一下如何在Spring中更好地控制它吗?虽然这不是最初问题的意图,但我感兴趣的是看看Spring如何处理这个问题。