I am pretty new in Spring MVC and I have a doubt about the session scope of a bean.
Into a project I have a Cart
bean, this one:
@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;
}
}
So this bean is automatically detected as component by the container and it is set as a session bean by:
@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
So, from what I have understand it means that it is automatically created a single bean for each user session.
In my example the Cart
class represent a shopping cart in which a logged user put the items that want buy. Does it mean that there exists a single Cart
bean for each logged user section into the HttpSession
? So this bean is into the session and the user can add or delete item from it. Is this interpretation right or am I missing something?
Another doubt is related to the proxyMode = ScopedProxyMode.TARGET_CLASS
attribute. What exactly does that mean? Why is it applied to this bean?
So, from what I have understand it means that it is automatically created a single bean for each user session.
The session bean will be created per user, but only when requested. In other words, if, for a given request, you don't actually need that bean, the container will not create it for you. It's, in a sense, "lazy".
The typical use is
@Controller
public class MyController {
@Autowired
private MySessionScopeBean myBean;
// use it in handlers
}
Here, you're injecting a session scoped bean into a singleton scope bean. What Spring will do is inject a proxy bean, that, internally, will be able to generate a real MySessionScopeBean
object per user and store it in the HttpSession
.
The annotation attribute and value
proxyMode = ScopedProxyMode.TARGET_CLASS
defines how Spring will proxy your bean. In this case, it will proxy by retaining the target class. It will use CGLIB for this purpose. An alternative is INTERFACES
where Spring uses JDK proxies. These do not retain the class type of the target bean, only its interfaces.
You can read more about proxies here:
Here's a related post about the request scope: