您的位置:首页 > 编程语言 > Java开发

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中才能够有效。这里我仅仅是粗滤地讲解,如何配置使用这三种作用域。但其对应的测试用例就不编写了。
   要使用request
、[code]session
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
作用域类似于标准的HTTP
Session
作用域,不过它仅仅在基于portlet的web应用中才有意义。Portlet规范定义了全局
Session
的概念,它被所有构成某个portletweb应用的各种不同的portlet所共享。在
global session
作用域中定义的bean被限定于全局portlet
Session
的生命周期范围内。具体配置如下:[/code]
<?xml version="1.0" encoding="UTF-8"?>
   以上就是Spring bean作用域的内容,Spring bean作用域还有一些内容,比如如何自定义作用域等,但限于篇幅且并不常用,所以这里就不深究了。谢谢您的浏览。

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: