Блок try-catch-finally в Java

Насколько я понимаю, я хочу следовать передовой практике для освобождения ресурсов в конце, чтобы предотвратить любые утечки соединения. Вот мой код в HelperClass.

public static DynamoDB getDynamoDBConnection()
{   
    try
    {
        dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
    }
    catch(AmazonServiceException ase)
    {
        //ase.printStackTrace();
        slf4jLogger.error(ase.getMessage());
        slf4jLogger.error(ase.getStackTrace());
        slf4jLogger.error(ase);
    }
    catch (Exception e)
    {
        slf4jLogger.error(e);
        slf4jLogger.error(e.getStackTrace());
        slf4jLogger.error(e.getMessage());
    }
    finally
    {
        dynamoDB.shutdown();
    }
    return dynamoDB;
}

Я сомневаюсь, что, так как блок finally будет выполнен независимо от того, будет ли DynamoDB возвращать пустое соединение, потому что он будет закрыт в блоке finally, а затем выполнит оператор return? ТИА.

4 ответа

Решение

Ваше понимание верно. dynamoBD.shutdown() всегда будет выполняться раньше return dynamoDB,

Я не знаком с фреймворком, с которым вы работаете, но я бы, вероятно, организовал код следующим образом:

public static DynamoDB getDynamoDBConnection()
        throws ApplicationSpecificException {   
    try {
        return new DynamoDB(new AmazonDynamoDBClient(
                                    new ProfileCredentialsProvider()));
    } catch(AmazonServiceException ase) {
        slf4jLogger.error(ase.getMessage());
        slf4jLogger.error(ase.getStackTrace());
        slf4jLogger.error(ase);
        throw new ApplicationSpecificException("some good message", ase);
    }
}

и использовать его как

DynamoDB con = null;
try {
    con = getDynamoDBConnection();
    // Do whatever you need to do with con
} catch (ApplicationSpecificException e) {
    // deal with it gracefully
} finally {
    if (con != null)
        con.shutdown();
}

Вы также можете создать AutoCloseable обертка для подключения к DynamoDB (которая вызывает shutdown внутри close) и делать

try (DynamoDB con = getDynamoDBConnection()) {
    // Do whatever you need to do with con
} catch (ApplicationSpecificException e) {
    // deal with it gracefully
}

Да, DynamoDB вернет пустое соединение как dynamoBD.shutdow() будет выполнен перед оператором return Всегда.

Хотя я не отвечаю на ваш вопрос о том, что блок finally выполняется всегда (на этот вопрос уже есть несколько ответов), я хотел бы поделиться некоторой информацией о том, как ожидается использование клиентов DynamoDB.

Клиент DynamoDB является потокобезопасным объектом и предназначен для совместного использования несколькими потоками - вы можете создать глобальный объект для своего приложения и повторно использовать этот объект там, где он вам нужен. Обычно создание клиента управляется каким-либо контейнером IoC (например, контейнером Spring IoC), а затем предоставляется контейнером для любого кода, в котором он нуждается, путем внедрения зависимостей.

Под капотом клиент DynamoDB поддерживает пул HTTP-соединений для связи с конечной точкой DynamoDB и использует соединения из этого пула. Различные параметры пула можно настроить, передав экземпляр объекта ClientConfiguration при создании клиента. Например, одним из параметров является максимально допустимое количество открытых HTTP-соединений.

С учетом вышеизложенного я бы сказал, что, поскольку клиент DynamoDB управляет жизненным циклом HTTP-соединений, утечки ресурсов на самом деле не должны касаться кода, использующего клиент DynamoDB.

Как насчет "подражать" ошибке и посмотреть, что произойдет? Это то, что я имею в виду:

___Случай 1___

try{
  // dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
  throw new AmazonServiceException("Whatever parameters required to instantiate this exception");
}    catch(AmazonServiceException ase)
    {
        //ase.printStackTrace();
        slf4jLogger.error(ase.getMessage());
        slf4jLogger.error(ase.getStackTrace());
        slf4jLogger.error(ase);

    }
    catch (Exception e)
    {
        slf4jLogger.error(e);
        slf4jLogger.error(e.getStackTrace());
        slf4jLogger.error(e.getMessage());
    }
    finally
    {
        //dynamoDB.shutdown();
        slf4jLogger.info("Database gracefully shutdowned");
    }

___ Случай 2___

try{
  // dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
  throw new Exception("Whatever parameters required to instantiate this exception");
}    catch(AmazonServiceException ase)
    {
        //ase.printStackTrace();
        slf4jLogger.error(ase.getMessage());
        slf4jLogger.error(ase.getStackTrace());
        slf4jLogger.error(ase);

    }
    catch (Exception e)
    {
        slf4jLogger.error(e);
        slf4jLogger.error(e.getStackTrace());
        slf4jLogger.error(e.getMessage());
    }
    finally
    {
        //dynamoDB.shutdown();
        slf4jLogger.info("Database gracefully shutdowned");
    }

Эти упражнения могут быть идеальным местом для использования модульных тестов и, в частности, пробных тестов. Я предлагаю вам поближе познакомиться с JMockit, который поможет вам гораздо легче писать такие тесты.

Другие вопросы по тегам