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

来源:互联网 发布:c语言编程软件手机版 编辑:程序博客网 时间:2024/05/15 07:28

        一张配方,可以用于生产很多相同的东西。在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实例。当然,口头上这样讲,没有什么信服力,我们还是用测试用例来证明一下。

 
    在编写的测试用例中,向容器发出两次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作用域测试用例如下:
   

   在测试用例中,也是发出了两次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 定义。

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

   在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