Spring容器中Bean的作用域

来源:互联网 发布:钢材进销存软件 编辑:程序博客网 时间:2024/05/21 10:33

  当我们通过Spring容器创建一个Bean实例时,不仅可以完成该Bean的实例化,而且还可以指定该Bean的作用域,Spring支持的五种作用域如下:

singleton:单例模式,singleton作用域下的Bean将只产生一个实例,因此我们每次获取的实例都是同一实例。

prototype:每次通过getBean()方法获取Bean实例时,都会产生一个新的Bean实例,因此每次的实例都不同

request:用于Web应用,对于一次Http请求,request作用域内的Bean只生成一个Bean,也就是说同一次请求内,每次获取该Bean,

      获取的都是同一实例,但是如果到了下次请求(刷新页面)就会再次产生一个Bean实例,但是在每次的请求内多次获取

      Bean实例都是同一实例。

session:对于一次http会话,session作用域的Bean将只生成一个实例,仅在Web应用中该作用域才会真的有效。

global session:每个全局的HttpSession对应一个实例

如果不单独在配置文件中设置,默认的作用域为singleton作用域。

一:singleton作用域对比prototype作用域

1:配置文件beans.xml

        <!-- 配置一个默认的singleton Bean实例 --><bean id="p1" class="com.mao.scope.Person"/><!-- 配置一个prototype Bean实例 --><bean id="p2" class="com.mao.scope.Person" scope="prototype"/><!-- 配置一个默认的singleton Bean实例 --><bean id="date" class="java.util.Date"/>

上面配置了两个默认的singleton Bean,一个prototype Bean。

Bean 实例是实现类Person就是一个最简单的java类,这里不再给出。

2:下面主程序测试BeanTest.java

import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class BeanTest {public static void main(String []args) throws InterruptedException{ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");//singleton作用域  只生成一个实例 因此返回实例相同System.out.println(ctx.getBean("p1")==ctx.getBean("p1"));//prototype作用域 每次都会生成一个实例,因此返回的实例不同System.out.println(ctx.getBean("p2")==ctx.getBean("p2"));//线程虽然休眠了一秒,但是此作用域为singleton 所以在创建容器时date Bean就已经创建完了,属于一个实例//因此两次的输出时间相同System.out.println(ctx.getBean("date"));Thread.sleep(1000);System.out.println(ctx.getBean("date"));}}

3:输出结果


  可以看出,singleton作用域的Bean,仅产生一个Bean实例,因此每次获取的实例时是同一Bean实例,但是prototype作用域的Bean实例,每次请求都会产生新的Bean实例,因此两次Bean实例并不相同,

值得注意的是,上面分两次获取了系统时间,虽然中间线程休眠了一秒,但是输出时间却相同,这是因为咱们在配置文件beans.xml定义的date Bean的时候是默认的singleton作用域,也就是说在创建Spring容器的时候,date Bean实例就已经创建出来了,虽然咱们获取了两次,但是singletype作用域仅仅产生一个实例,因此两次都是同一实例,所以输出的时间是相同的,但是如果我们将date Bean实例的作用域指定成scope="prototype",每次获取都会产生新的实例,再看结果:


这样就时间相差了一秒,这也说明了prototype作用域的Bean,每次获取的都是新创建的不同实例。

二:request作用域

request作用域仅对Web应用有效,因此需要在Web应用中需要额外配置。request作用域对于每次Http请求会产生一个实例,在同一次请求中获取的Bean实例是相同的。

1:新建Web项目

2:导入Jar文件

  将所有需要的Jar文件复制到项目WEB-INF\lib路径下,注意只能是此路径,Web应用默认在此路径加载Jar文件,而不是用户自定义的类库(java项目可以将Spring所需的jar放在用户自定义的路径下)。

3:修改Web配置文件Web.xml,添加如下:

<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><listener><listener-class>org.springframework.web.context.request.RequestContextListener</listener-class></listener>

4:创建spring配置文件applicationContext.xml  存放位置WEB-INF路径下

<?xml version="1.0" encoding="UTF-8"?><beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.0.xsd"><!-- 创建Bean 并指定request作用域 --><bean id="p" class="com.mao.requestScope.Person" scope="request"></bean></beans>

5:测试脚本 test.jsp 存放路径 WebContent路径下

<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %><%@ page import="org.springframework.web.context.*" %><%@ page import="org.springframework.web.context.support.*" %><%@ page import="com.mao.requestScope.*"%><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>Spring Bean的作用域</title></head><body><%// 获取Web应用初始化的Spring容器WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(application);// 两次获取容器中id为p的BeanPerson p1=(Person)ctx.getBean("p");Person p2 = (Person)ctx.getBean("p");out.println((p1 == p2) + "<br/>");out.println(p1);%></body></html>

6:运行结果


可以看出,request作用域内的Bean,每次访问都是同一实例,因此返回了true,但是如果我们刷新页面,再看结果


仔细对比两次结果,发现实例变了,这就说明,request作用域的Bean每次Http请求都会产生新的Bean实例,但是同一请求中访问Bean 都是同一实例,因此即使我们刷新页面,在这个请求下获取两次Bean实例,依然相同,返回了true。

0 0
原创粉丝点击