I'm trying to figure out how spring manages to inject thread safe request/session scoped bean in controller component (which is singleton and multiple threads accessing those beans through methods).
As example consider HttpServletRequest field in controller marked with @Autowired annotation (I know that this is bad to couple controller to servlet-api but in learning purposes it is ok). I learned that such beans are proxied using CGLib, but still cannot figure out how proxy can handle thread
safety and scope beans to current thread.
That's what I learned so far:
- from request to request controller field points on same instance (even in case of
HttpServletRequest) thread's stack trace from session scoped (proxied) transfer object method invocation
java.lang.Thread.getStackTrace(Thread.java:1552) com.company.market.to.User.setUid(User.java:73) com.company.market.to.User$$FastClassBySpringCGLIB$$8eb69e9e.invoke(<generated>) org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:133) org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:121) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655) com.company.market.to.User$$EnhancerBySpringCGLIB$$f4f46820.setUid(<generated>) com.company.market.controllers.UserController.signIn(UserController.java:97)As you can see some of the code is generated at runtime in methods by CGLib enhancer.
The only idea that comes in mind is ThreadLocal. DispatcherServlet holds reference to MethodInterceptor which has ThreadLocal field and then injects actual object (e.g. retrieved from session by getAttribute or simply HttpServletRequest) to that field, and then interceptor uses actual bean (stored in thread local) and using reflection invokes methods on original bean.
Any suggestions or interesting links appreciated!
Thanks.