Should I put my ThreadLocals in a spring-injected singleton?

后端 未结 4 1080
庸人自扰
庸人自扰 2020-12-13 07:26

Several people (eg at serverside http://www.theserverside.com/news/thread.tss?thread_id=41473) suggest that using ThreadLocal objects is as bad as using global variables. I

相关标签:
4条回答
  • 2020-12-13 08:04

    If you use Spring, you can simply use a request-scoped bean instead of explicit ThreadLocals:

    public interface UserName {
        ...
    }
    
    @Component 
    @Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
    public class UsernameImpl implements UserName { 
        private String username; 
        ...
    }
    
    0 讨论(0)
  • 2020-12-13 08:11

    ThreadLocals work great when you have common code that is handled by JMS, Queues and http requests. Request scoped values do not work in all the scenarios.

    One important thing to remember when using threadLocals is that threads will be re-used by the server container, so are the local variable values if something is set on it, if you have values that needs to be reset, use servlet filters/AOP proxy objects on the controllers/jms listeners to clear the values just before it invokes the business logic, or else you could end up debugging very hard to reproduce type of issues .

    0 讨论(0)
  • 2020-12-13 08:18

    As @axtavt mentioned, request-scoped beans are usually a cleaner and more elegant alternative to ThreadLocals when you're talking about web applications. In fact, under the covers, Spring implements request-scoped beans using its own ThreadLocal variables (see RequestContextHolder). Both ThreadLocal and scoped beans give you the same basic advantage - the ability to access the object without having to pass it down manually through the call stack.

    There is one scenario where ThreadLocal variales win over scoped beans, though, which is in cases where you want to access the object from outside of Spring's bean lifecycle. A good example of this is inside a JSP taglib. Taglib instances are controlled by the servlet container, not Spring, and so cannot participate in Spring's IoC framework, and so cannot be wired up with a request-scoped bean (or any other bean, for that matter). They can, however, access ThreadLocal variables. There are ways around this, but sometimes ThreadLocals are the easiest approach.

    One of the functional disadvantages of ThreadLocal is that they're not very useful in applications where data is passed from thread to thread (InheritableThreadLocal helps here sometimes, but not always). In such situations, Spring's scoped beans also fail, since they are implemented using ThreadLocal.

    So to advise on an approach, if you have a Spring webapp, with Spring beans that want access to objects that are specific to the current request thread, then I'd advise using request-scoped beans. If you need to access those objects beyond the control of Spring's beans, then ThreadLocal may be easier, although I'd try to make things work with scoped beans as much as possible.

    0 讨论(0)
  • 2020-12-13 08:22

    Spring uses ThreadLocals internally, and there is nothing wrong with having them as infrastructure. However, you should avoid them for business logic.

    If you really need them, and the request scope doesn't suit you (for some unforeseeable reason), then I'd advice defining a custom Scope, using ThreadLocal internally, thus hiding it from your business-logic.

    0 讨论(0)
提交回复
热议问题