Java 实现自动关闭-如何知道try块中是否发生异常?
我们编写了一个类,它打开了与服务器的连接。完成后,如果一切都成功,您需要告诉它执行Java 实现自动关闭-如何知道try块中是否发生异常?,java,try-with-resources,autocloseable,Java,Try With Resources,Autocloseable,我们编写了一个类,它打开了与服务器的连接。完成后,如果一切都成功,您需要告诉它执行commit,如果出现问题,您需要告诉它执行rollback。所以现在我们的代码中有很多点是这样的: OurConnectionClass conn = null; try { conn = OurConnectionClass(parameters); // Do some stuff here... conn.commit(); } catch (Throwable t) { i
commit
,如果出现问题,您需要告诉它执行rollback
。所以现在我们的代码中有很多点是这样的:
OurConnectionClass conn = null;
try {
conn = OurConnectionClass(parameters);
// Do some stuff here...
conn.commit();
} catch (Throwable t) {
if (conn != null) {
conn.rollback();
}
throw t;
}
如果忘记提交或回滚,则不会立即出现问题,但最终会耗尽连接池,然后必须找出错误所在
我想找到一种方法,使我们的ConnectionClass实现自动关闭,这样我就可以做如下设置:
try (OurConnectionClass conn = new OurConnectionClass(parameters)) {
// Do some stuff here...
}
我觉得一定有办法做到这一点,但我没有看到
AutoCloseable
只调用close
方法,不向其传递任何参数。就我所见,无法知道调用close是因为成功到达了try块的末尾,还是因为抛出了异常。执行此代码段时
try (OurConnectionClass conn = new OurConnectionClass(parameters)) {
// Do some stuff here...
conn.commit();
}
OurConnectionClass.close()
将始终在创建实例后调用。因此,您可以添加一些逻辑来检查是否进行了提交。例如,使用布尔
标志。这样,您就可以在close()
方法中检查连接是应该和平关闭还是应该回滚:
public class OurConnectionClass implements AutoCloseable{
private boolean committed; // initialized to false
public void commit(){
// commit
committed = true;
}
public void close() throws Exception{
if(!committed){
// rollback
}
}
}
我认为您想要的语义是事务在关闭时回滚,除非使用OurConnectionClass explicit的代码调用OurConnectionClass.commit() 那么您就没有任何问题了,因为您的close方法只需要测试是否存在打开的事务。如果有,请回滚,并记录错误。两者都要做
try (OurConnectionClass conn = new OurConnectionClass(parameters)) {
// Do some stuff here...
conn.commit();
} catch (Throwable t) {
conn.rollback();
throw t;
}
如果东西爆炸,可关闭项仍然自动关闭(在隐式finally
块中)
顺便说一句,最好抛出一个域异常:
throw new MyStuffExploded(t);
因为重新抛出连接异常会让实现细节通过方法契约泄漏出来,这是一种耦合形式,这是不好的。现在我已经把这些都写出来了,我想知道我是否应该使用匿名函数而不是尝试使用
try with resources
?我可以让OurConnectionClass
接收并尝试运行它,如果成功,它会在之后运行commit()
,如果失败,它会在。。。我可以让它成为一个不返回任何内容的静态方法,而不是返回一个实例。听起来可能比我想象的要复杂一些。。。在尝试之前,我会先看看其他人对此有何想法……使用AutoClosable
您的意思是AutoClosable
?您能指定您所指的接口吗?请注意,如果构造函数失败并引发异常,则不会调用close()。根据,您可以在处理异常的try-with-resource块之后定义一个catch
-块。@Leviand-我从上下文中思考(事实上我说的是Java的try-with-resource)很明显,我指的是标准Java库中的AutoCloseable
接口,而不是第三方的接口。无论如何,你是对的,我在几个地方把这个名字拼错了。我已经修复了它。可能想让提交
易失性
@Bohemian:为什么?@Bohemian我不是很确定,但是try with resources
-中的逻辑最终是在不同的线程中执行的吗?。因为在twr
块中不应该有多个线程访问conn
,如果我正确理解了这个问题是的。。。这听起来确实比我们现在所做的有所改进,但我担心当开发人员忘记提交并且不知道发生了什么时会浪费时间。我可以让close调用而不提交两个调用回滚并抛出一个异常。我从未见过在没有发生异常的情况下使用回滚。我想我将深入研究使用lambdas来实现这一点,但是…是否应该只使用可丢弃的t
,或者更确切地说,根据它的重要性重新使用?