Spring之旅--Spring管理bean的作用域

        一张配方,可以用于生产很多相同的东西。在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>节点做简单的配置,配置如下:

 


  
  

  
  
           
   
   
	      
   
   
	      
   
   

  
  

   在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(studentService2));
	}
}
    在编写的测试用例中,向容器发出两次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作用域呢,如下配置。

   

   
   

   
   
           
    
    
	      
    
    
	      
	      
    
    
	      

   
   
   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中才能够有效。这里我仅仅是粗滤地讲解,如何配置使用这三种作用域。但其对应的测试用例就不编写了。

   要使用requestsessionglobal session作用域的bean(即具有web作用域的bean),开始设置bean定义之前,还要做少量的初始配置。需要注意的是,你必须根据实际的情况做出正确的配置。

   第一种情况,如果你用Spring Web MVC,即用SpringDispatcherServletDispatcherPortlet来处理请求,则不需要做特别的配置:DispatcherServletDispatcherPortlet已经处理了所有有关的状态。

   第二种情况,当使用了Spring's DispatcherServlet以外的Servlet 2.4及以上的Web容器时(如使用JSF或Struts),你需要在Web应用的'web.xml'文件中增加javax.servlet.ServletRequestListener 定义。


   
   

   
   
	
    
    
	
    
    
	
    
    
        
     
     
      
      org.springframework.web.context.request.RequestContextListener
     
     
    
    
    

   
   
   第三种情况, 如果你用的是早期版本的web容器(Servlet 2.4以前的版本),那么你要使用一个 javax.servlet.Filter 的实现。那么使用以下配置:

    
    

    
    

    
   
     
      
    
      
      
       
       requestContextFilter
      
       
    
      
      
       
       org.springframework.web.filter.RequestContextFilter
      
      
  
     
      
  
     
      
    
      
      
       
       requestContextFilter
      
       
    
      
      
       
       /*
      
      
  
     
     
       
    
    

    
    

   在web.xml中配置完成之后,便可在应用中使用这三种bean的作用域了。

   Request作用域:针对每次http请求,Spring 容器会根据bean定义创建一个全新的bean实例,且该实例仅在本次http request 请求内有效,因此可以根据需要放心的更改所建实例的内部状态,而其他http请求创建的bean实例,这些特定于某个请求的状态变化。当本次http request请求结束,request作用域的创建的bean实例将被销毁。request作用域的具体配置如下:


   
   

   
   
           
               
    
    
	           
    
    
	           

   
   

   Session作用域针对某个HTTPSession,Spring容器会根据bean定义创建一个全新的bean实例, 且该bean仅在当前HTTPSession内有效。 与request作用域一样,你可以根据需要放心的更改所创建实例的内部状态,而别的HTTPSession中根据bena定义创建的实例, 将不会看到这些特定于某个HTTPSession的状态变化。 当HTTPSession最终被废弃的时候,在该HTTPSession作用域内的bean也会被废弃掉。session作用域具体配置如下:


   
   

   
   
           
               
    
    
	           
    
    
	           

   
   

   Global session作用域:global session作用域类似于标准的HTTPSession作用域,不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局Session的概念,它被所有构成某个portlet web应用的各种不同的portlet所共享。在global session作用域中定义的bean被限定于全局portletSession的生命周期范围内。具体配置如下:


   
   

   
   
           
               
    
    
	           
    
    
	           

   
   

   以上就是Spring bean作用域的内容,Spring bean作用域还有一些内容,比如如何自定义作用域等,但限于篇幅且并不常用,所以这里就不深究了。谢谢您的浏览。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值