Spring之旅--Spring管理bean的作用域
2017-02-10 12:57
501 查看
一张配方,可以用于生产很多相同的东西。在Sprig中,bean定义也是如此,创建一个bean定义,其实质就是用该bean定义对应的类创建真正实例的"配方"。根据bean定义,我们 可以创建多个实例对象。在bean定义中,你不仅可以控制注入到对象中的各种依赖和配置值,还可以控制该对象的作用域,这样你可以灵活选择所建对象的作用域。 Spring 框架支持五种作用域:singleton作用域、prototype作用域、request作用域、session作用域,global session作用域。其中request、session、global session 三种作用域仅能用在基于web的Spring
ApplicationContext 中。也就是说,在web项目中,方可使用。今天呢,我们就来分别探讨这五种作用域及如何配置使用。
Singleton作用域:当一个bean的作用域为singleton,那么在IOC容器中,有且仅有一个共享的bean实例,并且对于所有的bean请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。换句话说,当把一个bean定义设置为singlton作用域时,Spring IoC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都将返回被缓存的对象实例。官方文档示意图如下。
那么,我们该如何设置一个bean的作用域为singleton呢?很简单,只需在配置文件中的<bean>节点做简单的配置,配置如下:<?xml version="1.0" encoding="UTF-8"?>
在bean.xml配置文件中,将bean的作用域设置为singleton之后呢,那么Spring IOC容器会根据配置,只创建一个bean实例,且缓存起来,以后对于每次bean请求,都只会返回同一个bean实例。当然,口头上这样讲,没有什么信服力,我们还是用测试用例来证明一下。
package junit.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mars.spring.ioc.MyTestClassPathXMLApplicationContext; import com.mars.spring.service.StudentService; /** * 单元测试用例 * @author Administrator * */ public class SpringTest { @Test public void testScope(){ //初始化容器 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); //获取bean对象 StudentService studentService1 = (StudentService)context.getBean("studentService1"); StudentService studentService2 = (StudentService)context.getBean("studentService2"); //如果bean对象相同,那么两个引用必定指向同一个对象,结果为true System.out.println(studentService1.equals(studentServ 4000 ice2)); } }在编写的测试用例中,向容器发出两次bean请求,容器返回两个bean实例。比较两个bean实例,如果结果为true,那么说明是同一个实例,则说明singleton作用域只存在一个bean实例。反之结果为false,那么说明singleton作用域存在多个bean实例。运行测试用例,结果如下:
测试用例运行结果为true,则说明两次请求的bean对象为同一个bean对象,同时说明在singleton作用域中,容器有且仅存一个bean实例。
Prototype作用域:Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。下图演示Spring 的prototype作用域;
上图演示了在Spring的prototype作用域,Spring IOC容器创建bean的过程,那么在配置文件中如何配置bean为prototype作用域呢,如下配置。
<?xml version="1.0" encoding="UTF-8"?>prototype作用域测试用例如下:
package junit.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mars.spring.ioc.MyTestClassPathXMLApplicationContext; import com.mars.spring.service.StudentService; /** * 单元测试用例 * @author Administrator * */ public class SpringTest { @Test public void testScope(){ //初始化容器 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); //获取bean对象 StudentService studentService1 = (StudentService)context.getBean("studentService1"); StudentService studentService2 = (StudentService)context.getBean("studentService2"); //如果bean对象相同,那么两个引用必定指向同一个对象,结果为true System.out.println(studentService1.equals(studentService2)); } }
在测试用例中,也是发出了两次bean请求,返回了两个对象,但在prototype作用域中,返回的两个对象须是不相同的,才能说明Spring IOC容器创建并返回了两个不相同的bean实例对象。测试用例运行结果如下。
测试用例运行结果为false,表明在prototype作用域下,Spring IOC容器对于每次bean请求都会创建不同的bean对象并返回。
以上两种作用域,是Spring中常用的作用域。根据经验呢,对于有状态的bean应当使用prototype作用域,而无状态的bean使用singleton作用域。在实际开发中,DAO不会配置成prototype作用域,因为DAO不会持有任何的会话状态,因此DAO配置成singleton作用域。
剩下三种作用域:request、session、global session,是基于web的Spring和ApplicationContext中才能够有效。这里我仅仅是粗滤地讲解,如何配置使用这三种作用域。但其对应的测试用例就不编写了。要使用、[code]sessionrequest
global session作用域的bean(即具有web作用域的bean),开始设置bean定义之前,还要做少量的初始配置。需要注意的是,你必须根据实际的情况做出正确的配置。[/code]
第一种情况,如果你用Spring Web MVC,即用SpringDispatcherServlet
或DispatcherPortlet来处理请求,则不需要做特别的配置:
DispatcherServlet和
DispatcherPortlet已经处理了所有有关的状态。[/code]
第二种情况,当使用了Spring's DispatcherServlet以外的Servlet 2.4及以上的Web容器时(如使用JSF或Struts),你需要在Web应用的'web.xml'
文件中增加javax.servlet.ServletRequestListener定义。[/code]
<?xml version="1.0" encoding="UTF-8"?>org.springframework.web.context.request.RequestContextListener第三种情况,如果你用的是早期版本的web容器(Servlet 2.4以前的版本),那么你要使用一个
javax.servlet.Filter的实现。那么使用以下配置:
<?xml version="1.0" encoding="UTF-8"?>requestContextFilterorg.springframework.web.filter.RequestContextFilterrequestContextFilter/*
在web.xml中配置完成之后,便可在应用中使用这三种bean的作用域了。Request作用域:针对每次http请求,Spring 容器会根据bean定义创建一个全新的bean实例,且该实例仅在本次http request 请求内有效,因此可以根据需要放心的更改所建实例的内部状态,而其他http请求创建的bean实例,这些特定于某个请求的状态变化。当本次http request请求结束,request作用域的创建的bean实例将被销毁。request作用域的具体配置如下:
<?xml version="1.0" encoding="UTF-8"?>
Session作用域:针对某个HTTP
Session,Spring容器会根据bean定义创建一个全新的bean实例,且该bean仅在当前HTTP
Session内有效。 与
request作用域一样,你可以根据需要放心的更改所创建实例的内部状态,而别的HTTP
Session中根据bena定义创建的实例,将不会看到这些特定于某个HTTP
Session的状态变化。 当HTTP
Session最终被废弃的时候,在该HTTP
Session作用域内的bean也会被废弃掉。session作用域具体配置如下:
<?xml version="1.0" encoding="UTF-8"?>
Global session作用域:global session
作用域类似于标准的HTTPSession作用域,不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局
Session的概念,它被所有构成某个portletweb应用的各种不同的portlet所共享。在
global session作用域中定义的bean被限定于全局portlet
Session的生命周期范围内。具体配置如下:[/code]
<?xml version="1.0" encoding="UTF-8"?>
以上就是Spring bean作用域的内容,Spring bean作用域还有一些内容,比如如何自定义作用域等,但限于篇幅且并不常用,所以这里就不深究了。谢谢您的浏览。
相关文章推荐
- spring三种实例化Bean的方式和管理Bean的作用域和Bean的生命周期
- Spring管理的bean的作用域
- 传智播客Spring2.5视频教程_配置Spring管理的bean的作用域 1
- 传智播客Spring2.5视频教程_配置Spring管理的bean的作用域 2
- Spring管理的Bean的作用域
- ITCAST视频-Spring学习笔记(配置Spring管理的bean的作用域)
- 配置Spring管理的bean的作用域
- spring学习笔记整理--04(配置Spring管理的bean的作用域、生命周期)
- Spring第五弹—–配置Spring管理的bean的作用域和生命周期
- spring2.5.6学习笔记六:配置Spring管理的bean的作用域
- (转)配置Spring管理的bean的作用域
- 【SSH三大框架】Spring基础第一篇:搭建Spring环境、实例化Bean、管理Bean的作用域以及Bean的生命周期
- 配置Spring管理的bean的作用域
- 在不同环境下调用Spring来管理的Bean.
- Spring学习笔记(1):Bean的生命周期管理
- 详解Spring中bean的作用域
- 传智播客Spring2.5视频教程_Spring管理的Bean的生命周期 2
- spring中bean的作用域
- Spring中bean的作用域
- ITCAST视频-Spring学习笔记(Spring管理的Bean的生命周期)