Spring Область запроса vs java thread-local

В больших объемах (~ 50 000 запросов в секунду) Java-приложение Я использую ThreadLocal для выполнения задачи, которая должна выполняться в области запроса.

Я мог бы добиться такого же эффекта, используя область запроса Spring, и я задался вопросом, какая из них лучше?

В коде, используя ThreadLocal:

private static final ThreadLocal<SomeClass> myThreadLocal = new ThreadLocal<SomeClass>();

И для каждого параметра http-запроса:

myThreadLocal.set(new SomeClass());

Использование области запроса Spring:

@Component
@Scope("request")
public class SomeClass{
...
}

Теперь, что будет стоить дороже:

myThreadLocal.get();

ИЛИ

SpringContext.getBean(SomeClass.class);

Интересно, кто-нибудь уже пробовал такой тест?

Ответ 1

Если мы рассмотрим традиционный подход Java, ответ может быть вычтен из приведенной ниже цитаты как более медленный:

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

Цитата из JavaDoc об отражении - http://java.sun.com/docs/books/tutorial/reflect/index.html

Так как Spring использует Отражение с помощью метода getBean(), подход SpringContext.getBean(SomeClass.class); должен быть медленнее.

ИЗМЕНИТЬ

Также обратите внимание, что ThreadLocal также имеет кэширование встроенных, так что если вы повторно используете информацию в этих потоках, это будет быстрее.

Ответ 2

Решение Spring будет стоить дороже, но сделает для более чистого кода IMO. Существует множество шагов, связанных с извлечением, созданием, инициализацией и хранением bean. Однако вам не придется думать об очистке области запроса bean, как вы бы ThreadLocal. Он будет собран, когда очищается соответствующая ServletRequest.

Ответ 3

Что касается решения ThreadLocal, я хотел бы добавить, что на вашем веб-сервере есть, вероятно, пул потоков (например, Tomcat), и локальная переменная вашего потока на самом деле не будет очищена после завершения каждого запроса в качестве потоков обработки не умирайте с включенным пулом потоков.

Вам необходимо очистить локальную переменную потока (threadLocal.remove()) вручную после завершения каждого запроса. Для этого вы можете использовать, например, некоторый тип afterCompletion() некоторых из этих Spring перехватчиков запроса/ответа.