Восстановление сохраненных значений в блоке finally? - PullRequest
2 голосов
/ 20 января 2011

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

Вот пример из Google Guice (Servlet) 3.0:

Context previous = localContext.get();

try {
  localContext.set(new Context((HttpServletRequest) servletRequest,
      (HttpServletResponse) servletResponse));

  //dispatch across the servlet pipeline, ensuring web.xml's filterchain is honored
  filterPipeline.dispatch(servletRequest, servletResponse, filterChain);
} finally {
  localContext.set(previous);
}

Какая необходимость или выгода для восстановления значения в блоке finally?

Ответы [ 3 ]

5 голосов
/ 20 января 2011

Это в основном способ определения изменений только для блока try.Независимо от того, успешно ли выполняется блок, вы знаете, что когда вы вышли из него, вы восстановили значение до того, что было, когда вы вошли.

4 голосов
/ 20 января 2011

Это очень полезный шаблон, который эффективно эмулирует нелексическую область видимости в Java. Предположим, что локальный контекст по сути является глобальной переменной или, чаще, локальной переменной потока. Вы изменяете глобальное значение на заданное значение (потому что, например, вы не хотите передавать каждому и каждому методу, называемому HTTP-запросом и ответом), который может быть получен позже, в методах, находящихся глубоко в стеке вызовов. Если вы хотите вложить эти модификации, одно исключение может вывести вас из строя - отсюда и эта конструкция. Независимо от того, что происходит (за исключением сбоя виртуальной машины или принудительного завершения процесса ОС), этот блок будет выполнен, когда стек раскручивается, и его задача - отменить изменение глобальных переменных, поскольку вложенность функциональности больше не существует. необходимо.

См. Также тему # setContextClassLoader ().

0 голосов
/ 20 января 2011

Я попытаюсь привести еще один пример, где мы находим этот шаблон полезным.В сущности, говорится: «Восстановите (обычно) глобальные ресурсы в предсказуемое состояние после того, как блок try / catch будет выполнен с их использованием».

Пример: Мы используем пул соединений с БД => Мы понимаем созданиеновые соединения стоят дорого, и мы хотели бы повторно использовать ограниченный пул соединений.Таким образом, блок try в некотором классе сервлетов начинается с Connection, создает его Statement и ResultSet, записывает результаты в ObjectOutputStream и т. Д. Это может вызвать SQLException (кто-то удалил бесполезный столбец в таблице db, и sql теперь не работает) и / илиIOException (клиентское соединение http разорвано, пока сервлет все еще пишет в него), которое мы перехватываем в блоке catch.Теперь, вне зависимости от того, сгенерировано исключение или нет, мы хотим закрыть соединение с БД, чтобы другие потоки могли его использовать.Это закрытие выполняется в блоке finally.

Надеюсь, это поможет, - MS

...