When you declare a bean in the configuration file, you are actually defining a template for bean creation, not an actual bean instance. When a bean is requested by the getBean() method or a reference from other beans, Spring will decide which bean instance should be returned according to the bean scope. Sometimes you have to set an appropriate scope for a bean other than the default scope.
In Spring 2.x, a bean’s scope is set in the scope attribute of the <bean> element. By default, Spring creates exactly one instance for each bean declared in the IoC container, and this instance will be shared in the scope of the entire IoC container. This unique bean instance will be returned for all subsequent getBean() calls and bean references. This scope is called singleton, which is the default scope of all beans. The table lists all valid bean scopes in Spring.
Scope | Description |
singleton | Creates a single bean instance per Spring IoC container |
prototype | Creates a new bean instance each time when requested |
request | Creates a single bean instance per HTTP request; only valid in the context of a web application |
session | Creates a single bean instance per HTTP session; only valid in the context of a web application |
globalSession | Creates a single bean instance per global HTTP session; only valid in the context of a portal application |
In Spring 1.x, singleton and prototype are the only two valid bean scopes, and they are specified by the singleton attribute (i.e., singleton="true" or singleton="false"), not the scope attribute.
How It Works
To demonstrate the concept of bean scope, let’s consider a shopping cart example in your shop application. First, you create the ShoppingCart class as follows:
package com.shop; … public class ShoppingCart { private List<Product> items = new ArrayList<Product>(); public void addItem(Product item) { items.add(item); } public List<Product> getItems() { return items; } }
Then you declare some product beans and a shopping cart bean in the IoC container as usual:
<beans …> <bean id="aaa" class="com.shop.Battery"> <property name="name" value="AAA" /> <property name="price" value="2.5" /> </bean> <bean id="cdrw" class="com.shop.Disc"> <property name="name" value="CD-RW" /> <property name="price" value="1.5" /> </bean> <bean id="dvdrw" class="com.shop.Disc"> <property name="name" value="DVD-RW" /> <property name="price" value="3.0" /> </bean> <bean id="shoppingCart" class="com.shop.ShoppingCart" /> </beans>
In the following Main class, you can test your shopping cart by adding some products to it. Suppose that there are two customers navigating in your shop at the same time. The first one gets a shopping cart by the getBean() method and adds two products to it. Then, the second customer also gets a shopping cart by the getBean() method and adds another product to it.
package com.shop; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Product aaa = (Product) context.getBean("aaa"); Product cdrw = (Product) context.getBean("cdrw"); Product dvdrw = (Product) context.getBean("dvdrw"); ShoppingCart cart1 = (ShoppingCart) context.getBean("shoppingCart"); cart1.addItem(aaa); cart1.addItem(cdrw); System.out.println("Shopping cart 1 contains " + cart1.getItems()); ShoppingCart cart2 = (ShoppingCart) context.getBean("shoppingCart"); cart2.addItem(dvdrw); System.out.println("Shopping cart 2 contains " + cart2.getItems()); } }
As a result of the preceding bean declaration, you can see that the two customers get the same shopping cart instance.
Shopping cart 1 contains [AAA 2.5, CD-RW 1.5] Shopping cart 2 contains [AAA 2.5, CD-RW 1.5, DVD-RW 3.0]
This is because Spring’s default bean scope is singleton, which means Spring creates exactly one shopping cart instance per IoC container.
<bean id="shoppingCart" class="com.shop.ShoppingCart" scope="singleton" /> <!– Caution: this is the default if scope is not present –>
In your shop application, you expect each customer to get a different shopping cart instance when the getBean() method is called. To ensure this behavior, you should change the scope of the shoppingCart bean to prototype. Then Spring will create a new bean instance for each getBean() method call and reference from the other bean.
<bean id="shoppingCart" class="com.shop.ShoppingCart" scope="prototype" />
Now if you run the Main class again, you can see that the two customers get a different shopping cart instance.
Shopping cart 1 contains [AAA 2.5, CD-RW 1.5] Shopping cart 2 contains [DVD-RW 3.0]