Я должен поместить свой ThreadLocals во введенный пружиной одиночный элемент?

Несколько человек (например, в серверной стороне 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 является объявлением что этот класс использование та переменная.

Каковы преимущества и недостатки этого подхода?

14
задан Bozho 7 February 2010 в 21:08
поделиться

3 ответа

Если вы используете Spring, вы можете просто использовать запрос -scoped bean вместо явного ThreadLocal s:

public interface UserName {
    ...
}

@Component 
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public class UsernameImpl implements UserName { 
    private String username; 
    ...
}
11
ответ дан 1 December 2019 в 07:19
поделиться

Spring использует внутри ThreadLocal , и нет ничего плохого в том, чтобы использовать их в качестве инфраструктуры . Однако вам следует избегать их для бизнес-логики .

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

6
ответ дан 1 December 2019 в 07:19
поделиться

Как упоминалось в @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-компонентами с ограниченной областью действия, насколько это возможно.

19
ответ дан 1 December 2019 в 07:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: