복붙노트

[SPRING] ThreadLocals을 스프링 주입 싱글 톤에 넣어야합니까?

SPRING

ThreadLocals을 스프링 주입 싱글 톤에 넣어야합니까?

여러 사람들 (예 : 서버 http://www.theserverside.com/news/thread.tss?thread_id=41473)은 ThreadLocal 객체를 사용하는 것이 전역 변수를 사용하는 것만 큼 나쁘다고 제안합니다. 당신이 그것들을 public static 변수로 만들면 이것이 사실이라고 상상해보십시오. 문제는 그 곳이 어디에서 사용되고, 어디에서 바뀌 었는지 등을 밝히기가 어려울 수 있다는 것입니다.

내 봄 DI 바람둥이 웹 애플 리케이션에서, 그냥 내 봄에 내 ThreadLocal (s)가있는 싱글 톤 객체를 생성하고 그 싱글 톤을 필요로하는 모든 클래스에 삽입하면이 문제를 해결하는 것으로 보인다.

그래서 내 싱글 톤은 다음과 같이 보입니다.

@Component
public class Username {
    private ThreadLocal<String> username;

    public Username() {
        username = new ThreadLocal<String>();
    }

    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는이 클래스가 해당 변수를 사용한다는 선언입니다.

이 접근법의 장단점은 무엇입니까?

해결법

  1. ==============================

    1.Spring을 사용한다면 명시 적 ThreadLocals가 아닌 요청 범위 Bean을 사용할 수있다.

    Spring을 사용한다면 명시 적 ThreadLocals가 아닌 요청 범위 Bean을 사용할 수있다.

    public interface UserName {
        ...
    }
    
    @Component 
    @Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
    public class UsernameImpl implements UserName { 
        private String username; 
        ...
    }
    
  2. ==============================

    2.@axtavt가 언급했듯이, 요청 범위 Bean은 일반적으로 웹 애플리케이션에 대해 이야기 할 때 ThreadLocals에 대한보다 깨끗하고보다 우아한 대안입니다. 사실, Spring은 자체 ThreadLocal 변수 (RequestContextHolder 참조)를 사용하여 요청 범위 Bean을 구현한다. ThreadLocal과 Scoped Bean 모두 동일한 기본 이점을 제공합니다. 호출 스택을 통해 수동으로 전달하지 않고도 객체에 액세스 할 수있는 기능입니다.

    @axtavt가 언급했듯이, 요청 범위 Bean은 일반적으로 웹 애플리케이션에 대해 이야기 할 때 ThreadLocals에 대한보다 깨끗하고보다 우아한 대안입니다. 사실, Spring은 자체 ThreadLocal 변수 (RequestContextHolder 참조)를 사용하여 요청 범위 Bean을 구현한다. ThreadLocal과 Scoped Bean 모두 동일한 기본 이점을 제공합니다. 호출 스택을 통해 수동으로 전달하지 않고도 객체에 액세스 할 수있는 기능입니다.

    Spring의 bean 생명주기 외부에서 객체에 접근하기를 원할 경우, Scopeed Bean을 통해 ThreadLocal varial이 승리하는 시나리오가 있습니다. 이것의 좋은 예가 JSP taglib 내부입니다. Taglib 인스턴스는 Spring이 아닌 서블릿 컨테이너에 의해 제어되기 때문에 Spring의 IoC 프레임 워크에 참여할 수 없으므로 요청 범위의 Bean (또는 다른 Bean)과 연결할 수 없다. 그러나 이들은 ThreadLocal 변수에 액세스 할 수 있습니다. 이 문제를 해결하는 방법이 있지만 때로는 ThreadLocals가 가장 쉬운 방법입니다.

    ThreadLocal의 기능적 단점 중 하나는 데이터가 스레드에서 스레드로 전달되는 응용 프로그램에서 그다지 유용하지 않다는 점입니다 (InheritableThreadLocal은 때때로 여기에서 도움이되지만 항상 그런 것은 아닙니다). 이러한 상황에서 Spring의 범위가 지정된 bean은 ThreadLocal을 사용하여 구현되기 때문에 실패합니다.

    접근법을 조언하기 위해 현재 요청 스레드에 특정한 객체에 대한 액세스를 원하는 Spring 빈을 사용하는 Spring 웹 애플리케이션이 있다면 request-scoped beans를 사용하는 것이 좋습니다. Spring Bean의 제어를 넘어서 이러한 객체에 액세스해야하는 경우 가능한 한 범위가 좁은 Bean으로 작업하도록 만들지 만 ThreadLocal이 더 쉬울 수도 있습니다.

  3. ==============================

    3.Spring은 내부적으로 ThreadLocals를 사용하며 인프라로 사용하는 데는 아무런 문제가 없습니다. 그러나 비즈니스 로직을 위해 이들을 피해야합니다.

    Spring은 내부적으로 ThreadLocals를 사용하며 인프라로 사용하는 데는 아무런 문제가 없습니다. 그러나 비즈니스 로직을 위해 이들을 피해야합니다.

    정말 필요하고 요청 범위가 당신에게 어울리지 않는다면 (예기치 않은 이유로), 내부적으로 ThreadLocal을 사용하여 사용자 정의 범위를 정의하는 조언을 얻을 수 있으므로 비즈니스 논리에서 숨길 수 있습니다.

  4. ==============================

    4.ThreadLocals는 JMS, 큐 및 http 요청에 의해 처리되는 공통 코드가있을 때 유용합니다. 요청 범위 값이 모든 시나리오에서 작동하지 않습니다.

    ThreadLocals는 JMS, 큐 및 http 요청에 의해 처리되는 공통 코드가있을 때 유용합니다. 요청 범위 값이 모든 시나리오에서 작동하지 않습니다.

    threadLocals를 사용할 때 기억해야 할 중요한 점 중 하나는 스레드가 서버 컨테이너에 의해 다시 사용된다는 것입니다. 그래서 뭔가가 설정되어 있으면 지역 변수 값이 재설정됩니다. 재설정해야하는 값이 있으면 서블릿 필터 / AOP 프록시를 사용하십시오 컨트롤러 / jms 리스너의 객체가 비즈니스 로직을 호출하기 직전에 값을 지우거나 디버깅을 끝내면 문제 유형을 재현 할 수 있습니다.

  5. from https://stackoverflow.com/questions/2218282/should-i-put-my-threadlocals-in-a-spring-injected-singleton by cc-by-sa and MIT license