[英]Spring session bean shared between HttpSession-s
I'm trying to undestand session beans in Spring. 我试图在春季不理解会话bean。 The book I'm reading says, about them, that:
我正在阅读的书对它们说:
the bean is created when needed and stored in the javax.servlet.http.HttpSession.
该bean在需要时创建,并存储在javax.servlet.http.HttpSession中。 When the session is destoyed so is the bean instance.
当会话被保存时,bean实例也被保存。
I tried with the following example: 我尝试使用以下示例:
The bean: 豆:
package com.at.test.web;
public class Cart {
public static int dummy = 0;
public Cart() {
System.out.println("Cart::<init> with hashCode " + hashCode());
}
}
The bean definition: Bean的定义:
<beans:bean id="cartBean" class="com.at.test.web.Cart" scope="session">
<apo:scoped-proxy/>
</beans:bean>
The controller: 控制器:
@Controller
public class HomeController {
@Autowired
private Cart cart;
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(HttpSession session, Model model) {
System.out.println("Cart is: " + cart.hashCode()
+ " ; dummy = " + (cart.dummy++)
+ " (" + cart.getClass().getCanonicalName() + ")"
+ "; session is: " + session.hashCode());
return "home.jsp";
}
}
This is what happens on Tomcat startup: 这是在Tomcat启动时发生的情况:
Cart::<init> with hashCode 970109301
I think Spring need this instance in order to create the CGLIB proxies. 我认为Spring需要此实例才能创建CGLIB代理。 Anyway, I'm not that sure.
无论如何,我不确定。
After the startup, I use two different browsers to have two different HttpSession. 启动后,我使用两个不同的浏览器来拥有两个不同的HttpSession。 The result, when the controller is invoked, is:
调用控制器时,结果为:
Cart is: 578093288 ; dummy = 0 (com.at.test.web.Cart$$EnhancerByCGLIB$$2eb8334f); session is: 1013723725
Cart is: 578093288 ; dummy = 1 (com.at.test.web.Cart$$EnhancerByCGLIB$$2eb8334f); session is: 1060682497
The cart instance seems to be shared between HttpSession-s, but I was expecting two instances of Cart. cart实例似乎在HttpSession-s之间共享,但是我期望有两个Cart实例。
The same if I let the bean implements an interface, use annotation-driven approch and component scan: 如果我让Bean实现一个接口,则使用注释驱动的方法和组件扫描也是一样:
public interface ICart {}
-- -
@Component
@Scope(value="session", proxyMode=ScopedProxyMode.INTERFACES)
public class Cart implements ICart {
public static int dummy = 0;
public Cart() {
System.out.println("Cart::<init> with hashCode " + hashCode());
}
}
Am I missing something? 我想念什么吗? Did I misunderstood the meaning of session bean?
我是否误解了会话bean的含义?
public class HomeController {
@Autowired
private Cart cart; <-- Proxy
The Cart
instance that gets injected into the HomeController
instance is only a proxy that delegates method calls to the "real" instance. 注入到
HomeController
实例中的Cart
实例仅仅是将方法调用委托给“真实”实例的代理。 The Cart
class itself has no own method or state yet, so you won't notice any difference between sessions, of course. Cart
类本身还没有自己的方法或状态,因此您当然不会注意到会话之间的任何区别。
There's a lot of proxying and delegation going on. 正在进行很多代理和委派。
This field 这个领域
@Autowired
private Cart cart;
where Cart
is session scoped will be proxied as you can see in your logs 如您在日志中所见,将在会话范围内对
Cart
进行代理
com.at.test.web.Cart$$EnhancerByCGLIB$$2eb8334f
But this proxy is not wrapping a Cart
object. 但是此代理未包装
Cart
对象。 It is wrapping a SimpleBeanTargetSource
which takes care of getting a Cart
bean from the BeanFactory
. 它包装了一个
SimpleBeanTargetSource
,它负责从BeanFactory
获取Cart
Bean。
Your bean definition attaches a SessionScope
object which is responsible for checking your HttpSession
through a static
ThreadLocal
field in RequestContextHolder
. 您的bean定义附加一个
SessionScope
对象,该对象负责通过RequestContextHolder
的static
ThreadLocal
字段检查HttpSession
。 When request is made to get a bean from the BeanFactory
, it will delegate the action to the SessionScope
object which will check the HttpSession
, use the one there if it exists or create and register a new one if it doesn't. 当请求从
BeanFactory
获取一个bean时,它将把动作委托给SessionScope
对象,该对象将检查HttpSession
,如果存在则使用HttpSession
,否则创建并注册一个新的HttpSession
。
You don't notice this with your test because 您在测试中没有注意到这一点,因为
cart.hashCode()
delegates to the SimpleBeanTargetSource
object (incorrectly, if you ask me). 委托给
SimpleBeanTargetSource
对象(如果您问我的话,则是错误的)。 But if you did 但是如果你做到了
cart.toString();
you would see the difference as that actually reaches the underlying Cart
object. 您会看到实际到达基础
Cart
对象的差异。
Depending on the scope and proxying strategy you use, all this may be different, but the end goal is still achieved. 根据您使用的范围和代理策略,所有这些可能有所不同,但最终目标仍然可以实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.