Ich möchte zwei zwei verschiedene Methoden laufen in catch
und final
Blöcke. Ich habe festgestellt AutoCloseable
Schnittstelle, aber ich brauche nur etwas Feuer bei Ausnahme.
Mögen:
SomeService service = CreateService().andOpenTransaction()
try {
service.doSomeMessyThingsInsideDB();
} catch (Exception e) {
service.rollbackTransaction();
throw e;
} finally {
service.closeConnection();
}
Gibt es eine Möglichkeit, es einfacher zu machen? Wie ich sagte, ich bin vertraut mit AutoCloseable, aber es hilft mir nur mit finally-Block. Ich kann es immer noch nicht in dem Fang verwenden.
Nun könnten Sie Ihre eigene Schnittstelle definieren, und dann einige static
Läufer - Methode:
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;
}
}
}
Was Sie dann dann so nennen könnte:
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(); }
});
Aber sehen Sie, es ist immer noch chaotisch.
Man könnte sogar diese implementieren interface
in Ihrem SomeService
aber dann sind Sie beschränkt , dass die run()
Methode immer nennen doSomeMessyThingsInsideDB()
.
Ein anderer Weg , aber immer noch ähnlich wäre Java8 zu verwenden , und erstellen Sie einen Helfer funktional interface
:
public interface ThrowingRunnable {
void run() throws Exception;
}
Und dann eine static
Methode irgendwo:
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;
}
}
Der interessante Teil ist dies wahrscheinlich: try(AutoCloseable ao = onFinally)
, die „Register“ Ihre onFinally
Methode aufgerufen werden , wenn finally
erreicht wird.
Dies könnte dann wie folgt aufgerufen werden:
execute(
service::doSomeMessyThingsInsideDB,
service::rollbackTransaction,
service::closeConnection
);