bean 的会话作用域如何在 Spring MVC 应用程序中工作?
How does the session scope of a bean work in a Spring MVC application?
我是 Spring MVC 的新手,我对 bean 的 会话范围 有疑问。
进入一个项目我有一个 Cart
bean,这个:
@Component
@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Cart {
private Map<Product, Integer> contents = new HashMap<>();
public Map<Product, Integer> getContents() {
return contents;
}
public Set<Product> getProducts() {
return contents.keySet();
}
public void addProduct(Product product, int count) {
if (contents.containsKey(product)) {
contents.put(product, contents.get(product) + count);
}
else {
contents.put(product, count);
}
}
public void removeProduct(Product product) {
contents.remove(product);
}
public void clearCart() {
contents.clear();
}
@Override
public String toString() {
return contents.toString();
}
public double getTotalCost() {
double totalCost = 0;
for (Product product : contents.keySet()) {
totalCost += product.getPrice();
}
return totalCost;
}
}
所以这个 bean 被容器自动检测为组件,并被设置为 session bean by:
@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
因此,据我了解,这意味着它会为每个用户会话自动创建一个 bean。
在我的示例中,Cart
class 代表一个购物车,已登录的用户将要购买的商品放入其中。这是否意味着 HttpSession
中的每个登录用户部分都存在一个 Cart
bean?所以这个 bean 进入会话,用户可以从中添加或删除项目。这种解释是正确的还是我遗漏了什么?
还有一个疑惑是和proxyMode = ScopedProxyMode.TARGET_CLASS
属性有关的。这到底是什么意思呢?为什么应用到这个bean?
So, from what I have understand it means that it is automatically
created a single bean for each user session.
会话 bean 将为每个用户创建,但仅在请求时创建。换句话说,如果对于给定的请求,您实际上不需要那个 bean,则容器不会为您创建它。从某种意义上说,它是 "lazy".
典型的用法是
@Controller
public class MyController {
@Autowired
private MySessionScopeBean myBean;
// use it in handlers
}
在这里,您将会话范围的 bean 注入到单例范围的 bean 中。 Spring 将做的是注入一个 proxy bean,在内部,它将能够为每个用户生成一个真正的 MySessionScopeBean
对象并将其存储在 HttpSession
.
注释属性和值
proxyMode = ScopedProxyMode.TARGET_CLASS
定义 Spring 将如何代理您的 bean。在这种情况下,它将通过保留目标 class 来代理。它将为此目的使用 CGLIB。另一种选择是 INTERFACES
,其中 Spring 使用 JDK 代理。这些不保留目标 bean 的 class 类型,仅保留其接口。
您可以在此处阅读有关代理的更多信息:
- What is the difference between JDK dynamic proxy and CGLib?
这里有一个关于请求范围的相关post:
我是 Spring MVC 的新手,我对 bean 的 会话范围 有疑问。
进入一个项目我有一个 Cart
bean,这个:
@Component
@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Cart {
private Map<Product, Integer> contents = new HashMap<>();
public Map<Product, Integer> getContents() {
return contents;
}
public Set<Product> getProducts() {
return contents.keySet();
}
public void addProduct(Product product, int count) {
if (contents.containsKey(product)) {
contents.put(product, contents.get(product) + count);
}
else {
contents.put(product, count);
}
}
public void removeProduct(Product product) {
contents.remove(product);
}
public void clearCart() {
contents.clear();
}
@Override
public String toString() {
return contents.toString();
}
public double getTotalCost() {
double totalCost = 0;
for (Product product : contents.keySet()) {
totalCost += product.getPrice();
}
return totalCost;
}
}
所以这个 bean 被容器自动检测为组件,并被设置为 session bean by:
@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
因此,据我了解,这意味着它会为每个用户会话自动创建一个 bean。
在我的示例中,Cart
class 代表一个购物车,已登录的用户将要购买的商品放入其中。这是否意味着 HttpSession
中的每个登录用户部分都存在一个 Cart
bean?所以这个 bean 进入会话,用户可以从中添加或删除项目。这种解释是正确的还是我遗漏了什么?
还有一个疑惑是和proxyMode = ScopedProxyMode.TARGET_CLASS
属性有关的。这到底是什么意思呢?为什么应用到这个bean?
So, from what I have understand it means that it is automatically created a single bean for each user session.
会话 bean 将为每个用户创建,但仅在请求时创建。换句话说,如果对于给定的请求,您实际上不需要那个 bean,则容器不会为您创建它。从某种意义上说,它是 "lazy".
典型的用法是
@Controller
public class MyController {
@Autowired
private MySessionScopeBean myBean;
// use it in handlers
}
在这里,您将会话范围的 bean 注入到单例范围的 bean 中。 Spring 将做的是注入一个 proxy bean,在内部,它将能够为每个用户生成一个真正的 MySessionScopeBean
对象并将其存储在 HttpSession
.
注释属性和值
proxyMode = ScopedProxyMode.TARGET_CLASS
定义 Spring 将如何代理您的 bean。在这种情况下,它将通过保留目标 class 来代理。它将为此目的使用 CGLIB。另一种选择是 INTERFACES
,其中 Spring 使用 JDK 代理。这些不保留目标 bean 的 class 类型,仅保留其接口。
您可以在此处阅读有关代理的更多信息:
- What is the difference between JDK dynamic proxy and CGLib?
这里有一个关于请求范围的相关post: