Java 自动关闭ish方法,但仅在捕获时运行
Java 自动关闭ish方法,但仅在捕获时运行,java,Java,我希望有两个不同的方法在catch和final块中运行。我找到了可自动关闭的接口,但我需要一些东西,以防出现异常。 比如: SomeService service = CreateService().andOpenTransaction() try { service.doSomeMessyThingsInsideDB(); } catch (Exception e) { service.rollbackTransaction(); throw e; } finally
我希望有两个不同的方法在
catch
和final
块中运行。我找到了可自动关闭的接口,但我需要一些东西,以防出现异常。
比如:
SomeService service = CreateService().andOpenTransaction()
try {
service.doSomeMessyThingsInsideDB();
} catch (Exception e) {
service.rollbackTransaction();
throw e;
} finally {
service.closeConnection();
}
有没有办法让它更简单?正如我所说,我熟悉AutoCloseable,但它只在finally block方面对我有帮助。我仍然不能在捕捉器内使用它。您说您熟悉自动关闭功能,但您没有使用它。
您是否考虑过使用try with resources
语句
您的代码可以简化为:
try (SomeService service = CreateService().andOpenTransaction()) {
service.doSomeMessyThingsInsideDB();
} catch(exception e){
service.rollbackTransaction();
throw e;
}
Oracle在这方面做得很好,包括示例
注意:try with resources语句可以像普通的try语句一样具有catch和finally块。在try with resources语句中,任何catch或finally块都会在声明的资源关闭后运行
回答你的问题,这是最简单的。
如果您的类没有实现Closeable
,那么您可以实现它,或者使用最终
好的,您可以定义自己的接口,然后使用一些静态
运行方法:
public interface ErrorHandlingCloseable extends AutoCloseable {
void run() throws Exception;
void onError(Exception e);
static void execute(ErrorHandlingClosable ehc) throws Exception {
try(ErrorHandlingClosable temp = ehc) {
ehc.run();
} catch(Exception e) {
ehc.onError(e);
throw e;
}
}
}
你可以这样称呼它:
SomeService service = CreateService().andOpenTransaction();
ErrorHandlingCloseable.execute(new ErrorHandlingCloseable() {
public void run() throws Exception { service.doSomeMessyThingsInsideDB(); }
public void onError(Exception e) { service.rollbackTransaction(); }
public void close() throws Exception { service.closeConnection(); }
});
execute(
service::doSomeMessyThingsInsideDB,
service::rollbackTransaction,
service::closeConnection
);
但你看,还是很乱
您甚至可以在SomeService
中实现这个接口
,但是您受到限制,run()
方法将始终调用dosomeMessynthingsInsidedB()
另一种方法(但仍然类似)是使用Java8并创建一个helper functional接口
:
public interface ThrowingRunnable {
void run() throws Exception;
}
然后是某个地方的静态方法:
public static void execute(ThrowingRunnable action,
ThrowingRunnable onCatch,
ThrowingRunnable onFinally) throws Exception {
try(AutoCloseable ao = onFinally) {
action.run();
} catch(Exception e) {
onCatch.run();
throw e;
}
}
有趣的部分可能是:try(AutoCloseable ao=onFinally)
,它“注册”您的onFinally
方法,以便在到达时调用
这可以这样称呼:
SomeService service = CreateService().andOpenTransaction();
ErrorHandlingCloseable.execute(new ErrorHandlingCloseable() {
public void run() throws Exception { service.doSomeMessyThingsInsideDB(); }
public void onError(Exception e) { service.rollbackTransaction(); }
public void close() throws Exception { service.closeConnection(); }
});
execute(
service::doSomeMessyThingsInsideDB,
service::rollbackTransaction,
service::closeConnection
);
第一步:处理异常
显然,您希望在某些关闭之前处理异常。然后,您需要在内部使用资源进行尝试来处理异常
/** throws RuntimeException */
void process(Callable<Void> work, Consumer<Exception> onFail) {
try {
work.call();
} catch (Exception e) {
onFail(e);
}
}
try (SomeService service = CreateService().andOpenTransaction()) {
process(() -> service.doSomeMessyThingsInsideDB(),
e -> {
service.rollbackTransaction();
throw new IllegalStateException(e);
});
}
/**引发运行时异常*/
作废流程(可调用的工作、消费者onFail){
试一试{
work.call();
}捕获(例外e){
onFail(e);
}
}
试试(SomeService=CreateService().和opentransaction()){
进程(()->service.doSomeMessyngsInsidedB(),
e->{
service.rollbackTransaction();
抛出新的非法状态异常(e);
});
}
这不是很令人满意,但同样集成了AutoCloseable,可能给出的用例太少
第二步:自动关闭
void processAutoClosing(供应商服务工厂、,
可调用的工作,用户onFail){
try(SV service=serviceFactory.get()){
过程(工作、失败);
}
}
进程自动关闭(…);
没有这样的接口,当捕捉到异常时,就只有自动关闭了。您可以用lambdas编写一个函数。为什么要从服务外部开始这个事务?恐怕我不能在catch块中使用“service”变量。这是我的问题。如果编译器允许我按照您编写的方式编写代码,我将不会有任何问题。我只是在寻找最好的模式:)看起来“尝试资源”在这种情况下不适合我。如果没有人能在一天结束前找到答案,我会将你的答案标记为“答案”。你的解决方案也缺少和OpenTransaction()
部分。@M.Prokhorov谢谢,我在方法执行之前添加了它。看起来很酷,但有点过分了。事实上,你回答了我的问题,所以要点还是要告诉你的:)@Arkadiusz欢迎你,我添加了另一种方法,通过使用Java8函数接口来实现你的愿望。这仍然是一个有点,但较少过度工程