在spring容器中,当你注册一个bean时,不仅可以指定该bean的各种依赖和配置值,你也可以指定该bean的作用域。
1.singleton作用域
在spring Ioc 容器中,一个bean只会产生一个实例。代码如下。
<bean id="studentBeanScope" class="" scope="singleton"></bean>
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
StudentBeanScope sbs1 =(StudentBeanScope) ac.getBean("studentBeanScope");
StudentBeanScope sbs2 =(StudentBeanScope) ac.getBean("studentBeanScope");
System.out.println(sbs1);
System.out.println(sbs2);
结果:
study.mvc.first.study.StudentBeanScope@39aeed2f
study.mvc.first.study.StudentBeanScope@39aeed2f
通过结果不难发现,当我们获得实例,每次输出的内存地址都是一样,说明该bean只有一个实例。
2.prototype作用域
每次获取该bean(如getBean)都会创建一个新的实例,代码如下。
<bean id="studentBeanScope" class="" scope="prototype"></bean>
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
StudentBeanScope sbs1 =(StudentBeanScope) ac.getBean("studentBeanScope");
StudentBeanScope sbs2 =(StudentBeanScope) ac.getBean("studentBeanScope");
System.out.println(sbs1);
System.out.println(sbs2);
结果:
study.mvc.first.study.StudentBeanScope@51565ec2
study.mvc.first.study.StudentBeanScope@675d3402
此时我们发现内存地址不一样了,说明不是同一个实例了。
3.request作用域
对于每次Http请求,spring 容器都会创建该bean一个新的实例,并且该实例只在当前请求内有效,当请求结束时,
request创建的实例也会被销毁。
<bean id="studentBeanScope" class="" scope="request"></bean>
@Controller
@RequestMapping("first/study/")
public class StudySpring {
@RequestMapping("test1")
@ResponseBody
public String test1(HttpServletRequest request){
ServletContext sc = request.getSession().getServletContext();
ApplicationContext ac1 = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
System.out.println(ac1.getBean("studentBeanScope"));
System.out.println("简单的测试例子");
return "成功";
}
我们测试时会发现,针对每次的http请求,所输出的内存地址都发生了变化,说明每次请求都创建了新的实例
4.session作用域
对于每次Http session,spring 容器也都会创建该bean一个新的实例,并且当Http session废弃时,该Http session内的实例也会被废弃。
<bean id="studentBeanScope" class="" scope="session"></bean>
@Controller
@RequestMapping("first/study/")
public class StudySpring {
@RequestMapping("test1")
@ResponseBody
public String test1(HttpServletRequest request){
ServletContext sc = request.getSession().getServletContext();
ApplicationContext ac1 = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
System.out.println(ac1.getBean("studentBeanScope"));
System.out.println("简单的测试例子");
return "成功";
}
结果:
study.mvc.first.study.StudentBeanScope@675d3402
study.mvc.first.study.StudentBeanScope@675d3402
study.mvc.first.study.StudentBeanScope@675d3402
此时我们发现。针对每次http请求,输出的内存并没有发生变化,这是为什么呢,因为此时还是相同的一个http session
除非关闭浏览器,重新打开。
总结:在我们通过web应用获取bean时(request作用域和session作用域),一定记得在web.xml配置
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
否则将会出现 No WebApplicationContext found: no ContextLoaderListener registered? 异常。
另外,如果一个bean没有配置作用域,默认的作用域就是singleton。
有解释不正确的地方,希望大家及时指出,多谢多谢!