AutoCloseable-ish método, mas apenas pode ser executada sobre a captura

Arkadiusz:


Gostaria de dois têm dois métodos diferentes em execução em catche finalblocos. Eu descobri AutoCloseableinterface, mas eu preciso de algo para fogo em caso de única exceção.
Gostar:

SomeService service = CreateService().andOpenTransaction()

try {
    service.doSomeMessyThingsInsideDB();
} catch (Exception e) {
    service.rollbackTransaction();
    throw e;
} finally {
    service.closeConnection();
}

Existe alguma maneira de torná-lo mais simples? Como eu disse eu estou familiarizado com AutoCloseable, mas isso me ajuda somente com bloco finally. Eu ainda não posso usá-lo dentro da captura.

Lino:

Bem, você pode definir sua própria interface, e então algum staticmétodo de corredor:

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;
         }
     }
}

Que você então poderia então chamar assim:

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(); }
});

Mas você vê, ainda é confuso.

Você pode até mesmo implementar isso interfaceno seu SomeService, mas, em seguida, você está restrito que o run()método irá sempre chamar doSomeMessyThingsInsideDB().


Outro caminho, mas ainda semelhante seria usar Java8 e criar um ajudante funcional interface:

public interface ThrowingRunnable {
   void run() throws Exception;
}

E então um staticem algum lugar método:

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;
   }
}

A parte interessante é provavelmente esta: try(AutoCloseable ao = onFinally)que "registros" o seu onFinallymétodo a ser chamado quando finallyé atingido.

Este poderia então ser chamado assim:

execute(
    service::doSomeMessyThingsInsideDB, 
    service::rollbackTransaction, 
    service::closeConnection
);

Acho que você gosta

Origin http://10.200.1.11:23101/article/api/json?id=478540&siteId=1
Recomendado
Clasificación