25 April 2019
Spring(3)----Bean Scope----part1
by Jerry Zhang
Type of Scopes
In the last two articles, we discussed Spring IoC and how to inject dependencies. Like traditional class, we can create more than one object instance of a class. In this article, I am going to discuss how to define the scopes of our beans.
Spring Framework has six scopes, and you can also create a custom scope.
Scope | Description |
---|---|
singleton | (Default) Scopes a single bean definition to a single object instance for each Spring IoC container. |
prototype | Scopes a single bean definition to any number of object instances. |
request | Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext. |
session | Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext. |
application | Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext. |
websocket | Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext. |
source: https://docs.spring.io/spring/docs/5.1.6.RELEASE/spring-framework-reference/core.html#beans-factory-scopes
singleton: only one instance in each context
This is the default scope. Anytime we try to get a bean, it is always the same bean. Let’s do an experiment:
- Declare two beans. Notice that we added a scope attribute in bean2.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="springioc.class007.Bean2" id="bean2" scope="singleton"/>
<bean class="springioc.class007.Bean1" id="bean1">
<property name="bean2" ref="bean2"/>
</bean>
</beans>
- bean2 is an instance variable of bean1
public class Bean1 {
private Bean2 bean2;
public Bean2 getBean2() {
return bean2;
}
public void setBean2(Bean2 bean2) {
this.bean2 = bean2;
}
@Override
public String toString() {
return "Bean1{" +
"bean2=" + bean2 +
'}';
}
}
public class Bean2 {
}
- Then, if we try to get bean2 many times, or get the bean2 inside bean1, it’s always the same bean.
public class Class007Test {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Bean2 bean2_1 = context.getBean("bean2", Bean2.class);
System.out.println("bean2_1 = " + bean2_1);
Bean2 bean2_2 = context.getBean("bean2", Bean2.class);
System.out.println("bean2_2 = " + bean2_2);
Bean1 bean1 = context.getBean("bean1", Bean1.class);
System.out.println("bean1 = " + bean1);
}
}
- Result:
bean2_1 = springioc.class007.Bean2@3234e239
bean2_2 = springioc.class007.Bean2@3234e239
bean1 = Bean1{bean2=springioc.class007.Bean2@3234e239}
Prototype: anytime we require a bean from the context, contain gives us a new bean/object
If we change the scope to prototype
, like this:
<bean class="springioc.class007.Bean2" id="bean2" scope="prototype"/>
- The result will change:
bean2_1 = springioc.class007.Bean2@3234e239
bean2_2 = springioc.class007.Bean2@3d921e20
bean1 = Bean1{bean2=springioc.class007.Bean2@36b4cef0}
Notice that the bean2 are different this time.
Nested scope: various scope combination for the outside bean and inside bean
bean2 is an instance variable of bean1, or ‘inside’ bean1. If we also specify a scope for bean1, different combinations lead to different result.
Our test code:
public class Class007Test {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
Bean1 bean1_1 = context.getBean("bean1", Bean1.class);
System.out.println("bean1_1 = " + bean1_1);
Bean1 bean1_2 = context.getBean("bean1", Bean1.class);
System.out.println("bean1_2 = " + bean1_2);
System.out.println("(bean1_1 == bean1_2) = " + (bean1_1 == bean1_2));
}
}
- Case1: bean1 is singleton, bean2 is singleton
Obviously, there is only one bean1 and only one bean2.
- Case2: bean1 is singleton, bean2 is prototype
test result:
bean1_1 = Bean1{bean2=springioc.class007.Bean2@3234e239}
bean1_2 = Bean1{bean2=springioc.class007.Bean2@3234e239}
(bean1_1 == bean1_2) = true
Inside bean1, bean2 is the same one. This is because the outside bean is singleton.
- Case3: bean1 is prototype, bean2 is singleton
bean1_1 = Bean1{bean2=springioc.class007.Bean2@3234e239}
bean1_2 = Bean1{bean2=springioc.class007.Bean2@3234e239}
(bean1_1 == bean1_2) = false
- Case4: bean1 is prototype, bean2 is also prototype
Obviously, they are all different.
bean1_1 = Bean1{bean2=springioc.class007.Bean2@2173f6d9}
bean1_2 = Bean1{bean2=springioc.class007.Bean2@307f6b8c}
(bean1_1 == bean1_2) = false
Use annotation to config a scope
Add an @Scope(“yourscope
”) above our bean class
@Component("testBean2")
@Scope("prototype")
public class TestBean {
}