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作用域还有一些内容,比如如何自定义作用域等,但限于篇幅且并不常用,所以这里就不深究了。谢谢您的浏览。


1. 用户与身体信息管理模块 用户信息管理: 注册登录:支持手机号 / 邮箱注册,密码加密存储,提供第三方快捷登录(模拟) 个人资料:记录基本信息(姓名、年龄、性别、身高、体重、职业) 健康目标:用户设置目标(如 “减重 5kg”“增肌”“维持健康”)及期望周期 身体状态跟踪: 体重记录:定期录入体重数据,生成体重变化曲线(折线图) 身体指标:记录 BMI(自动计算)、体脂率(可选)、基础代谢率(根据身高体重估算) 健康状况:用户可填写特殊情况(如糖尿病、过敏食物、素食偏好),系统据此调整推荐 2. 膳食记录与食物数据库模块 食物数据库: 基础信息:包含常见食物(如米饭、鸡蛋、牛肉)的名称、类别(主食 / 肉类 / 蔬菜等)、每份重量 营养成分:记录每 100g 食物的热量(kcal)、蛋白质、脂肪、碳水化合物、维生素、矿物质含量 数据库维护:管理员可添加新食物、更新营养数据,支持按名称 / 类别检索 膳食记录功能: 快速记录:用户选择食物、输入食用量(克 / 份),系统自动计算摄入的营养成分 餐次分类:按早餐 / 午餐 / 晚餐 / 加餐分类记录,支持上传餐食照片(可选) 批量操作:提供常见套餐模板(如 “三明治 + 牛奶”),一键添加到记录 历史记录:按日期查看过往膳食记录,支持编辑 / 删除错误记录 3. 营养分析模块 每日营养摄入分析: 核心指标计算:统计当日摄入的总热量、蛋白质 / 脂肪 / 碳水化合物占比(按每日推荐量对比) 微量营养素分析:检查维生素(如维生素 C、钙、铁)的摄入是否达标 平衡评估:生成 “营养平衡度” 评分(0-100 分),指出摄入过剩或不足的营养素 趋势分析: 周 / 月营养趋势:用折线图展示近 7 天 / 30 天的热量、三大营养素摄入变化 对比分析:将实际摄入与推荐量对比(如 “蛋白质摄入仅达到推荐量的 70%”) 目标达成率:针对健
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值