Несколько человек (например, в серверной стороне http://www.theserverside.com/news/thread.tss?thread_id=41473) предполагают, что использование объектов ThreadLocal настолько же плохо как использует глобальные переменные. Я предполагаю, что это верно при создании их общедоступными статическими переменными. Проблема тогда состоит в том, что может быть трудно сказать, где это используется, где это изменяется и т.д.
В моем пружинном веб-приложении кота DI это, кажется, решает эту проблему, если я просто заставляю пружину создавать одноэлементный объект, который имеет мой ThreadLocal (s) в нем, и затем введите тот одиночный элемент в любой класс, которому нужен он.
Таким образом, мой одиночный элемент похож на это:
@Component
public class Username {
private ThreadLocal username;
public Username() {
username = new ThreadLocal();
}
public String getUsername()
return username.get();
}
public void setUsername(String name) {
username.set(name);
}
}
И классы, которым, возможно, понадобился бы он, похожи на это:
@Service
public class addEntryTransaction {
@Autowired
Username username;
public void method() {
...
log("Method called by "+username.getUsername());
...
}
}
Это все еще обладает преимуществами не необходимости передать имя пользователя через многие слои, которые не заботятся, и поэтому хранение более простых параметров метода. @Autowired является объявлением что этот класс использование та переменная.
Каковы преимущества и недостатки этого подхода?
Если вы используете Spring, вы можете просто использовать запрос -scoped bean вместо явного ThreadLocal
s:
public interface UserName {
...
}
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public class UsernameImpl implements UserName {
private String username;
...
}
Spring использует внутри ThreadLocal
, и нет ничего плохого в том, чтобы использовать их в качестве инфраструктуры . Однако вам следует избегать их для бизнес-логики .
Если они вам действительно нужны, а область запроса
вам не подходит (по какой-то непредвиденной причине), я бы посоветовал определить пользовательскую Область
, используя ] ThreadLocal
внутренне, таким образом скрывая его от вашей бизнес-логики.
Как упоминалось в @axtavt, bean-компоненты с областью действия запроса обычно являются более чистой и элегантной альтернативой ThreadLocals, когда вы говорите о веб-приложениях. Фактически, под покровом Spring реализует bean-компоненты с ограниченным объемом запросов, используя свои собственные переменные ThreadLocal (см. RequestContextHolder
). И ThreadLocal, и bean-компоненты с областью видимости дают вам одно и то же основное преимущество - возможность доступа к объекту без необходимости передавать его вручную через стек вызовов.
Однако есть один сценарий, в котором переменные ThreadLocal побеждают компоненты с ограниченной областью видимости, а именно в тех случаях, когда вы хотите получить доступ к объекту извне жизненного цикла bean-компонента Spring. Хороший пример этого - внутри библиотеки тегов JSP. Экземпляры Taglib управляются контейнером сервлетов, а не Spring, и поэтому не могут участвовать в инфраструктуре IoC Spring, и поэтому не могут быть связаны с bean-компонентом с областью действия запроса (или любым другим bean-компонентом, если на то пошло). Однако они могут получить доступ к переменным ThreadLocal. Есть способы обойти это, но иногда ThreadLocals - самый простой подход.
Одним из функциональных недостатков ThreadLocal является то, что они не очень полезны в приложениях, где данные передаются от потока к потоку (InheritableThreadLocal помогает здесь иногда, но не всегда).В таких ситуациях bean-компоненты Spring с областью видимости также не работают, поскольку они реализованы с использованием ThreadLocal.
Итак, чтобы посоветовать подход, если у вас есть веб-приложение Spring с bean-компонентами Spring, которым нужен доступ к объектам, специфичным для текущего потока запроса, я бы посоветовал использовать bean-компоненты с ограниченным объемом запроса. Если вам нужно получить доступ к этим объектам, находящимся вне контроля компонентов Spring, тогда ThreadLocal может быть проще, хотя я бы постарался сделать все, чтобы все работало с bean-компонентами с ограниченной областью действия, насколько это возможно.