Bean的Scope 什么是?Bean的Scope定义了Bean的生命周期和在上下文中的可见性。
在Spring框架中共定义了6种Scope;
- singleton
- prototype
- request
- session
- application
- websocket
最后四个:request, session, application, websocket,只有在web应用中才能够被使用到。
1, Singleton Scope
用Singleton Scope来定义一个bean,意味着容器创建一个单例的bean。虽有对它的请求都会返回相同的对象,任何一方进行了修改,都会响应到其他使用的地方。如果不指定其他scope,singleton是默认的scope。
例子:
1,创建一个Persion类:
public class Persion {
private String name;
}
2, 用@Scope来定一个singleton的bean
@Configuration
public void PersonConfiguration{
@Bean
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
public Person personSingleton() {
return new Person();
}
}
3, 测试两个对象会影响同一个bean。
@Runwith(SpringJUnit4Test.class)
public class PersonConfigurationTest {
@Autowire
private ApplicationContext applicationContext;
@Test
public void should_refering_the_singleton_bean_when_two_object_modify_it(){
Object personAObject = applicationContext.getBean("personSingleton");
Object personBObject = applicationContext.getBean("personSingleton");
Assert.assertNotNull(personAObject);
Assert.assertNotNull(personBObject);
Person personA = (Person) personAObject;
Person PersonB = (Person) personBObject;
String nameA = "Nickname A";
String nameB = "Nickname B";
personA.setName(nameA);
Assert.assertThat(personB.getName(), is(nameA));
personB.setName(nameB);
Assert.assertThat(personA.getName(), is(nameB));
}
}
2, Prototype Scope
用Prototype Scope定义的bean,每次容器请求都会创建一个新的bean;
在之前的PersonConfiguration.java文件中添加一个新的bean,标示为prototype scope.
@Configuration
public void PersonConfiguration{
@Bean
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
public Person personSingleton () {
return new Person();
}
@Bean
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Person personPrototype () {
return new Person();
}
}
在PersonConfigurationTest.java中添加一个新的Test case:
@Test
public void shoud_not_refering_other_prototype_scope_type_when_modify_one() {
Object personAObject = applicationContext.getBean("personSingleton");
Object personBObject = applicationContext.getBean("personSingleton");
Assert.assertNotNull(personAObject);
Assert.assertNotNull(personBObject);
Person personA = (Person) personAObject;
Person PersonB = (Person) personBObject;
String nameX = "Nickname X";
personA.setName(nameX);
Assert.assertThat(personB.getName(), not(nameX));
}
3, 在 Web 方面使用的Scope
3.1 Request Scope
使用@Scope定一个Request Scope的bean
@Bean
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public Person requestCopePerson() {
return new Preson();
}
使用的WebApplicationContext中定义的SCOPE_REQUEST;
proxyMode是必要的,因为在Application Context实例化的时候,并没有实际的请求,Spring将会创建一个代理来进行注入,并在request需要的时候进行实例化。
3.2 Session Scope
使用@Scope定一个Session Scope的bean
@Bean
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public Person requestCopePerson() {
return new Preson();
}
3.3 Application Scope
使用@Scope定一个Application Scope的bean
@Bean
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public Person requestCopePerson() {
return new Preson();
}
3.4 websocket Scope
使用@Scope定一个websocket Scope的bean
@Bean
@Scope(value = “websocket”, proxyMode = ScopedProxyMode.TARGET_CLASS)
public Person requestCopePerson() {
return new Preson();
}
没有地方为websocket定义一个常量,因此指定的是"websocket"这个字符串。