Springbeans范围

此处只是转载Google翻译后:原文英文链接地址

在创建bean定义时,实际创建的是用于创建由该bean定义定义的类的实际实例的配方。bean定义是一个配方的想法很重要,因为这意味着,就像一个类一样,你可以从一个配方创建许多对象实例。

您不仅可以控制要插入到从特定bean定义创建的对象中的各种依赖项和配置值,还可以控制从特定bean定义创建的对象的范围。这种方法非常强大,使您可以灵活地选择 通过配置创建的对象的范围,而不必在Java类级别“烘焙”对象的范围。可以将Bean定义为部署在多个范围之一中:开箱即用,Spring Framework仅支持五个范围(其中三个范围仅在您使用Web感知时才可用 ApplicationContext)。

下面列出了支持开箱即用的范围:

Bean范围

范围描述

独生子

根据Spring IoC容器将单个bean定义范围限定为单个对象实例。

原型

将单个bean定义范围限定为任意数量的对象实例。

请求

将单个bean定义范围限定为单个HTTP请求的生命周期; 也就是说,每个HTTP请求都有自己的bean实例,它是在单个bean定义的后面创建的。仅在Web感知Spring的上下文中有效 ApplicationContext

会议

将单个bean定义范围限定为HTTP的生命周期Session。仅在Web感知Spring的上下文中有效 ApplicationContext

全球会议

将单个bean定义范围限定为全局HTTP的生命周期Session。通常仅在portlet上下文中使用时有效。仅在Web感知Spring的上下文中有效ApplicationContext

1单例范围

当bean是单例时, 将只管理bean的一个共享实例,并且对具有id与该bean定义匹配的id或s的bean的所有请求将导致Spring容器返回一个特定的bean实例。

换句话说,当您定义bean定义并将其作为单一作用域时,Spring IoC容器将只创建 该bean定义定义的对象的一个实例。此单个实例将存储在此类单例bean的缓存中,并且该命名Bean的所有后续请求和引用将导致返回缓存的对象。

请注意,Spring的单例bean概念与开创性的Gang of Four(GoF)模式书中定义的Singleton模式完全不同。GoF的单件硬码,使得一个对象的范围并且只有一个特定类的实例将永远被创建每 ClassLoader。Spring单例的范围最好按容器和每个bean描述。这意味着如果在单个Spring容器中为特定类定义一个bean,那么Spring容器将创建该bean定义所定义的一个且只有一个类的实例。单例范围是Spring中的默认范围。要将bean定义为XML中的单例,您可以像这样编写配置:

<span style="color:#000000"><span style="color:#000000">< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“accountService” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.DefaultAccountService”</span> />

< <span style="color:#3f5f5f"><em>! - 以下是等效的,虽然是冗余的(单例范围是默认值); 使用spring-beans-2.0.dtd  -</em></span> >
< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“accountService” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.DefaultAccountService” </span> <span style="color:#7f007f">scope</span> = <span style="color:#2a00ff">“singleton”</span> />

< <span style="color:#3f5f5f"><em>! - 以下是等效的并保留为spring-beans.dtd  -</em></span> >中的<span style="color:#3f5f5f"><em>向后兼容性</em></span>
< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“accountService” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.DefaultAccountService” </span> <span style="color:#7f007f">singleton</span> = <span style="color:#2a00ff">“true”</span> /></span></span>

2原型范围

bean的部署的非单例原型范围导致每次对该特定bean的请求时创建一个新的bean实例(也就是说,它被注入到另一个bean中,或者通过编程getBean()方法调用请求它 容器)。根据经验,您应该将原型范围用于所有有状态的bean,而单例范围应该用于无状态bean。

下图说明了Spring原型范围。 请注意,DAO通常不会被配置为原型,因为典型的DAO不会保持任何会话状态; 这个作者更容易重用单例图的核心。

要将bean定义为XML中的原型,您可以编写如下配置:

<span style="color:#000000"><span style="color:#000000">< <span style="color:#3f5f5f"><em>! - 使用spring-beans-2.0.dtd  -</em></span> >
< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“accountService” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.DefaultAccountService” </span> <span style="color:#7f007f">scope</span> = <span style="color:#2a00ff">“prototype”</span> />

< <span style="color:#3f5f5f"><em>! - 以下是等效的并保留为spring-beans.dtd  -</em></span> >中的<span style="color:#3f5f5f"><em>向后兼容性</em></span>
< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“accountService” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.DefaultAccountService” </span> <span style="color:#7f007f">singleton</span> = <span style="color:#2a00ff">“false”</span> /></span></span>

在原型范围中部署bean时需要注意一件非常重要的事情,因为bean的生命周期会略有变化。Spring不管理原型bean的完整生命周期:容器实例化,配置,装饰和组装原型对象,将其交给客户端,然后不再了解该原型实例。这意味着虽然 无论范围如何都将在所有对象上调用初始化生命周期回调方法,但在原型的情况下,任何已配置的销毁生命周期回调都 不会叫做。客户端代码负责清理原型范围的对象并释放原型bean所持有的任何昂贵资源。(让Spring容器释放原型范围bean使用的资源的一种可能方法是使用自定义bean后处理器,它将保存对需要清理的bean的引用。)

在某些方面,您可以在讨论原型范围的bean时考虑Spring容器角色,而不是Java 'new'运算符的替代品。过去这一点的所有生命周期方面都必须由客户端处理。(Spring容器中bean的生命周期在第4.5.1节“生命周期回调”节中进一步描述。)

3具有原型bean依赖关系的单例bean

当使用依赖于作为原型作用域的bean的单例作用域时,请注意 在实例化时解析依赖项。这意味着如果依赖项将原型范围的bean注入到单例范围的bean中,将实例化一个全新的原型bean,然后将依赖注入到单例bean中...... 但这就是全部。那个完全相同的原型实例将是唯一提供给singleton-scoped bean的实例,如果这是你想要的那样就没问题了。

但是,有时您真正想要的是单例范围的bean能够在运行时一次又一次地获取原型范围的bean的全新实例。在这种情况下,只有依赖项将原型范围的bean注入到单例bean中是没有用的,因为如上所述,只有在Spring容器实例化单例bean并解析和注入其依赖项时才会发生 一次。如果您需要在运行时一次又一次地获取(原型)bean的全新实例,则可以参考标题为第4.3.7节“方法注入”的部分。

[注意]向后兼容性说明:以XML格式指定生命周期范围

如果您'spring-beans.dtd'在bean定义文件中引用 DTD,并且您明确了bean的生命周期范围,则必须使用“ singleton”属性来表示生命周期范围(记住单例生命周期范围是默认值) 。如果您正在引用 'spring-beans-2.0.dtd'DTD或Spring 2.0 XSD架构,那么您将需要使用“ scope”属性(因为“ singleton”属性已从新DTD和XSD文件的定义中删除,而不是“ scope”属性)。

要完全清楚这一点,这意味着如果singleton在XML bean定义中使用“ ”属性,那么您必须在该文件中引用 'spring-beans.dtd'DTD 。如果使用“ ”属性,则必须引用该文件中的 DTD或 XSD 。scope'spring-beans-2.0.dtd''spring-beans-2.5.xsd'

4其他范围

其他范围,即request, sessionglobal session仅针对基于Web的应用程序中使用(而不管您使用的特定Web应用程序框架的使用,如果确实有的话)。为了将相关概念保存在参考文档中的一个位置,这里描述了这些范围。

[注意]注意

只有在使用Web感知Spring ApplicationContext 实现(例如 XmlWebApplicationContext)时,才能使用以下段落中描述的范围 。如果您尝试使用这些作用域普通的Spring IoC容器,如 XmlBeanFactory或 ClassPathXmlApplicationContext,你 得到一个 IllegalStateException抱怨未知的bean作用域。

4.1初始Web配置

为了支持豆的作用域的 requestsession以及 global session水平(网络范围的豆),之前你可以设置一下bean定义需要进行一些小的初始配置。请注意,这一额外的设置 ,如果你只是想使用“标准”范围(即singleton和prototype)要求。

现在,根据您的特定Servlet环境,有几种方法可以实现此初始设置...

如果您正在Spring Web MVC中访问作用域bean,即在Spring处理的请求中 DispatcherServlet,或者 DispatcherPortlet,则不需要特殊设置:DispatcherServlet并且 DispatcherPortlet已经公开了所有相关状态。

使用Servlet 2.4+ Web容器时,如果在Spring的DispatcherServlet之外处理请求(例如,在使用JSF或Struts时),则需要将以下内容添加javax.servlet.ServletRequestListener到Web应用程序'web.xml'文件中的声明中 。

<span style="color:#000000"><span style="color:#000000">< <span style="color:#3f7f7f">web-app</span> >
  ...
  < <span style="color:#3f7f7f">听众</span> >
    < <span style="color:#3f7f7f">listener-class</span> > org.springframework.web.context.request.RequestContextListener < <span style="color:#3f7f7f">/ listener-class</span> >
  < <span style="color:#3f7f7f">/ listener</span> >
  ...
< <span style="color:#3f7f7f">/ web-app</span> ></span></span>

如果您使用的是旧的Web容器(Servlet 2.3),则需要使用提供的 javax.servlet.Filter实现。'web.xml'如果您希望在Servlet 2.3容器上的Spring的DispatcherServlet之外的请求中访问Web范围的bean,请在下面找到必须包含在Web应用程序文件中的XML配置片段。(过滤器映射取决于周围的Web应用程序配置,因此您必须根据需要进行更改。)

<span style="color:#000000"><span style="color:#000000">< <span style="color:#3f7f7f">web-app</span> >
  ..
  < <span style="color:#3f7f7f">filter</span> >
    < <span style="color:#3f7f7f">filter-name</span> > requestContextFilter < <span style="color:#3f7f7f">/ filter-name</span> >
    < <span style="color:#3f7f7f">filter-class</span> > org.springframework.web.filter.RequestContextFilter < <span style="color:#3f7f7f">/ filter-class</span> >
  < <span style="color:#3f7f7f">/ filter</span> >
  < <span style="color:#3f7f7f">filter-mapping</span> >
    < <span style="color:#3f7f7f">filter-name</span> > requestContextFilter < <span style="color:#3f7f7f">/ filter-name</span> >
    < <span style="color:#3f7f7f">url-pattern</span> > / * < <span style="color:#3f7f7f">/ url-pattern</span> >
  < <span style="color:#3f7f7f">/ filter-mapping</span> >
  ...
< <span style="color:#3f7f7f">/ web-app</span> ></span></span>

而已。DispatcherServlet, RequestContextListener并且 RequestContextFilter所有操作完全相同,即将HTTP请求对象绑定到Thread为该请求提供服务的对象。这使得请求和会话范围的bean可以在调用链的下游进一步使用。

4.2请求范围

考虑以下bean定义:

<span style="color:#000000"><span style="color:#000000">< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“loginAction” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.LoginAction” </span> <span style="color:#7f007f">scope</span> = <span style="color:#2a00ff">“request”</span> /></span></span>

有了上面的bean定义,Spring容器将LoginAction使用'loginAction'每个HTTP请求的bean定义创建一个全新的bean 实例 。也就是说,'loginAction'bean将在HTTP请求级别有效地作用域。您可以根据需要更改或弄脏创建的实例的内部状态,安全地知道同样使用在同一'loginAction'bean定义背面创建的实例的其他请求 将不会在状态中看到这些更改它们特别针对个人要求。当请求完成处理时,将放弃作用于请求的bean。

4.3会话范围

考虑以下bean定义:

<span style="color:#000000"><span style="color:#000000">< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“userPreferences” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.UserPreferences” </span> <span style="color:#7f007f">scope</span> = <span style="color:#2a00ff">“session”</span> /></span></span>

有了上面的bean定义,Spring容器将UserPreferences使用'userPreferences'bean定义为单个HTTP的生命周期创建一个全新的bean 实例 Session。换句话说,'userPreferences'bean将在HTTP Session 级别上有效地作用域。就像request-scopedbean 一样,您可以根据需要更改创建的实例的内部状态,安全地知道Session同样使用在同一'userPreferences'bean定义背面创建的实例的其他HTTP 实例也 不会看到这些更改处于状态,因为它们特定于单个HTTP Session。当 Session最终丢弃HTTP Session时,也将丢弃作用于该特定HTTP的bean 。

4.4全局会话范围

考虑以下bean定义:

<span style="color:#000000"><span style="color:#000000">< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“userPreferences” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.UserPreferences” </span> <span style="color:#7f007f">scope</span> = <span style="color:#2a00ff">“globalSession”</span> /></span></span>

global session范围是类似于标准HTTP Session范围(上面刚刚描述),和真才有意义在基于portlet的web应用程序的上下文。portlet规范定义了Session在构成单个portlet Web应用程序的所有各种portlet之间共享的全局概念。在global session作用域中定义的Bean 的作用域(或绑定)到全局portlet的生存期Session

请注意,如果您正在编写基于Servlet的标准Web应用程序并将一个或多个bean定义为具有global session范围,则将使用标准HTTP Session范围,并且不会引发任何错误。

4.5作为依赖项的作用域

能够定义一个作用于HTTP请求的bean或者Session(或者你自己设计的自定义范围)的bean 都非常好,但Spring IoC容器的主要增值之一是它不仅管理实例化您的对象(bean),以及协作者(或依赖项)的连线。如果要将(例如)HTTP请求作用域bean注入另一个bean,则需要注入AOP代理来代替作用域bean。也就是说,您需要注入一个代理对象,该对象公开与范围对象相同的公共接口,但这足够聪明,能够从相关范围(例如HTTP请求)和委托方法中检索真实的目标对象调用真实对象。

[注意]注意

并不需要使用 <aop:scoped-proxy/>与和作用域为豆类结合singletons或 prototypes。尝试为单例bean创建一个作用域代理是一个错误(结果 BeanCreationException肯定会在这方面让你直截了当)。

让我们看看实现这一点所需的配置; 配置并不是非常复杂(只需要一行),但了解“ 为什么 ”以及它背后的“ 如何 ”非常重要。

<span style="color:#000000"><span style="color:#000000">< <span style="color:#3f7f7f">?xml version =“1.0”encoding =“UTF-8”?</span>>
< <span style="color:#3f7f7f">beans </span> <span style="color:#7f007f">xmlns</span> = <span style="color:#2a00ff">“http://www.springframework.org/schema/beans” </span>
       <span style="color:#7f007f">xmlns:xsi</span> = <span style="color:#2a00ff">“http://www.w3.org/2001/XMLSchema-instance” </span>
       <span style="color:#7f007f">xmlns:aop</span> = <span style="color:#2a00ff">“http:// www .springframework.org / schema / aop“ </span>
       <span style="color:#7f007f">xsi:schemaLocation</span> = <span style="color:#2a00ff">”http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd“</span> >

    < <span style="color:#3f5f5f"><em>! - 作为代理公开的HTTP会话范围的bean  -</em></span> >
    < <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“userPreferences” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.UserPreferences” </span> <span style="color:#7f007f">scope</span> = <span style="color:#2a00ff">“session”</span> >
          
          < <span style="color:#3f5f5f"><em>! - 这个下一个元素会影响周围bean的代理 -</em></span> >
          < <span style="color:#3f7f7f">aop:scoped-proxy</span> />
    < <span style="color:#3f7f7f">/ bean</span> >
    
    < <span style="color:#3f5f5f"><em>! - 一个单例范围的bean,它注入了上面的bean  -</em></span> >
    < <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“userService” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.SimpleUserService”</span> >
    
        < <span style="color:#3f5f5f"><em>! - 对代理'userPreferences'bean的引用 -</em></span> >
        < <span style="color:#3f7f7f">property </span> <span style="color:#7f007f">name</span> = <span style="color:#2a00ff">“userPreferences” </span> <span style="color:#7f007f">ref</span> = <span style="color:#2a00ff">“userPreferences”</span> />

    < <span style="color:#3f7f7f">/ bean</span> >
< <span style="color:#3f7f7f">/ beans</span> >
</span></span>

要创建这样的代理,您只需要将子 <aop:scoped-proxy/>元素插入到作用域bean定义中(您可能还需要类路径上的CGLIB库,以便容器可以实现基于类的代理;您还需要使用附录A ,基于XML Schema的配置)。所以,只要你为什么需要这<aop:scoped-proxy/>在豆类的定义元素的作用域request, sessionglobalSession和“ 在这里插入您的自定义范围 ”的水平?通过挑选以下bean定义可以最好地解释原因(请注意,以下'userPreferences' bean定义 不完整):

<span style="color:#000000"><span style="color:#000000">< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“userPreferences” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.UserPreferences” </span> <span style="color:#7f007f">scope</span> = <span style="color:#2a00ff">“session”</span> />

< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“userManager” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.UserManager”</span> >
    < <span style="color:#3f7f7f">property </span> <span style="color:#7f007f">name</span> = <span style="color:#2a00ff">“userPreferences” </span> <span style="color:#7f007f">ref</span> = <span style="color:#2a00ff">“userPreferences”</span> />
< <span style="color:#3f7f7f">/ bean</span> ></span></span>

从上面的配置可以看出,单例bean 'userManager'被注入了对HTTP Session-scoped bean 的引用'userPreferences'。这里的重点是'userManager'bean是一个单独的...它将在每个容器中实例化一次,并且它的依赖关系(在这种情况下只有一个, 'userPreferences'bean)也只会被注入(一次!)。这意味着'userManager'遗嘱(概念上)只对完全相同的 'userPreferences'对象进行操作,即最初注入的对象。当您将HTTP -scoped bean作为依赖项注入协作对象(通常)时,这不是您想要的 Session。相反,我们 想要的是一个单一 'userManager'对象,然后,对于HTTP的生命周期Session,我们希望查看和使用'userPreferences'特定于所述HTTP 的对象Session

而你需要的是注入某种对象,它暴露与类完全相同的公共接口 UserPreferences(理想情况下是一个 UserPreferences 实例的对象 ),并且足够聪明,能够real UserPreferences从任何底层范围内获取 对象我们选择的机制(HTTP请求 Session等)。然后我们可以安全地将这个代理对象注入到'userManager' bean中,这将很幸运地意识到UserPreferences它所持有的 引用是一个代理。在这个例子中,当一个 UserManager实例在依赖注入的UserPreferences 对象上调用一个方法时,它实际上是在代理上调用一个方法......然后代理将关闭并UserPreferences 从(在这种情况下)获取真实对象HTTP Session,并将方法调用委托给检索到的真实 UserPreferences对象。

这就是为什么你注射时需要满足以下条件,正确而完整的配置request-, session-和 globalSession-scoped豆到协作对象:

<span style="color:#000000"><span style="color:#000000">< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“userPreferences” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.UserPreferences” </span> <span style="color:#7f007f">scope</span> = <span style="color:#2a00ff">“session”</span> >
    < <span style="color:#3f7f7f">aop:scoped-proxy</span> />
< <span style="color:#3f7f7f">/ bean</span> >

< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“userManager” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.UserManager”</span> >
    < <span style="color:#3f7f7f">property </span> <span style="color:#7f007f">name</span> = <span style="color:#2a00ff">“userPreferences” </span> <span style="color:#7f007f">ref</span> = <span style="color:#2a00ff">“userPreferences”</span> />
< <span style="color:#3f7f7f">/ bean</span> ></span></span>

选择创建的代理类型

默认情况下,当Spring容器为使用该<aop:scoped-proxy/>元素标记的bean 创建代理时,将创建基于CGLIB的类代理。这意味着您需要在应用程序的类路径上安装CGLIB库。

注意:CGLIB代理只会拦截公共方法调用!不要在这样的代理上调用非公开方法; 它们不会被委托给作用域目标对象。

您可以选择让Spring容器为这样的作用域bean创建“标准”基于JDK接口的代理,方法是为元素false的' proxy-target-class'属性 值指定' ' <aop:scoped-proxy/>。使用基于JDK接口的代理确实意味着您不需要在应用程序的类路径上使用任何其他库来实现此类代理,但它确实意味着作用域bean的类必须实现至少一个接口,并且所有协作者必须注入scoped bean必须通过其中一个接口引用bean。

<span style="color:#000000"><span style="color:#000000">< <span style="color:#3f5f5f"><em>! -  DefaultUserPreferences实现UserPreferences接口 -</em></span> >
< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“userPreferences” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.DefaultUserPreferences” </span> <span style="color:#7f007f">scope</span> = <span style="color:#2a00ff">“session”</span> >
    < <span style="color:#3f7f7f">aop:scoped-proxy </span> <span style="color:#7f007f">proxy-target-class</span> = <span style="color:#2a00ff">“false”</span> />
< <span style="color:#3f7f7f">/ bean</span> >

< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“userManager” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.UserManager”</span> >
    < <span style="color:#3f7f7f">property </span> <span style="color:#7f007f">name</span> = <span style="color:#2a00ff">“userPreferences” </span> <span style="color:#7f007f">ref</span> = <span style="color:#2a00ff">“userPreferences”</span> />
< <span style="color:#3f7f7f">/ bean</span> ></span></span>

题为第8.6节“代理机制”的部分也可能对理解选择基于类或基于接口的代理是否适合您的细微差别有一定的兴趣。

5自定义范围

从Spring 2.0开始,Spring中的bean作用域机制是可扩展的。这意味着您不仅限于Spring提供的开箱即用的bean范围; 您可以定义自己的范围,甚至可以重新定义现有范围(尽管最后一个范围可能被认为是不好的做法 - 请注意,您 不能覆盖内置 singletonprototype 范围)。

5.1创建自己的自定义范围

范围由org.springframework.beans.factory.config.Scope 接口定义 。这是您需要实现的接口,以便将您自己的自定义作用域集成到Spring容器中,并在下面详细介绍。您可能希望查看ScopeSpring Framework本身提供的 实现,以了解如何实现自己的实现。该范围的Javadoc解释当你需要你自己的范围,更详细得来实现主类。

Scope接口有四种方法,用于处理从作用域中获取对象,将其从作用域中删除,并允许在需要时“销毁”它们。

第一种方法应该从基础范围返回对象。例如,会话范围实现将返回会话范围的bean(如果它不存在,则在将其绑定到会话以供将来引用之后返回该bean的新实例)。

<span style="color:#000000"><span style="color:#000000">Object get(String name,ObjectFactory objectFactory)</span></span>

第二种方法应该从基础范围中删除对象。例如,会话范围实现从基础会话中删除会话范围的bean。应该返回该对象(如果找不到具有指定名称的对象,则允许返回null)

<span style="color:#000000"><span style="color:#000000">对象删除(字符串名称)</span></span>

第三种方法用于注册范围应在销毁时或在范围内的指定对象被销毁时应执行的回调。有关销毁回调的更多信息,请参阅Javadoc或Spring作用域实现。

<span style="color:#000000"><span style="color:#000000"><span style="color:#7f0055"><strong>void</strong></span> registerDestructionCallback(String name,Runnable destructionCallback)</span></span>

最后一种方法涉及获取基础范围的对话标识符。每个范围的标识符都不同。例如,对于会话,这可以是会话标识符。

<span style="color:#000000"><span style="color:#000000">String getConversationId()</span></span>

5.2使用自定义范围

在编写并测试了一个或多个自定义 Scope实现之后,您需要让Spring容器知道您的新范围。Scope使用Spring容器注册new的核心方法是在ConfigurableBeanFactory接口上声明的(由Spring附带的 大多数具体 BeanFactory实现实现); 这个中心方法显示如下:

<span style="color:#000000"><span style="color:#000000"><span style="color:#7f0055"><strong>void</strong></span> registerScope(String scopeName,Scope scope);</span></span>

registerScope(..)方法的第一个参数 是与范围关联的唯一名称; Spring容器本身的这些名称的例子是'singleton'和 'prototype'。该registerScope(..)方法的第二个参数 是Scope 您希望注册和使用的自定义实现的实际实例。

假设您已经编写了自己的自定义 Scope实现,并且已经注册了它:

<span style="color:#000000"><span style="color:#000000"><span style="color:#3f5f5f"><em>//注意:ThreadScope类不附带Spring Framework</em></span> 
Scope customScope = <span style="color:#7f0055"><strong>new</strong></span> ThreadScope();
beanFactory.registerScope(<span style="color:#2a00ff">“thread”</span>,customScope);</span></span>

然后,您可以创建符合自定义的作用域规则的bean定义,Scope如下所示:

<span style="color:#000000"><span style="color:#000000">< <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“...” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“...” </span> <span style="color:#7f007f">scope</span> = <span style="color:#2a00ff">“thread”</span> /></span></span>

如果您有自己的自定义Scope 实现,则不仅限于自定义范围的编程注册。您也可以 Scope使用CustomScopeConfigurer该类以声明方式进行注册。

Scope使用CustomScopeConfigurer该类的自定义实现 的声明性注册 如下所示:

<span style="color:#000000"><span style="color:#000000">< <span style="color:#3f7f7f">?xml version =“1.0”encoding =“UTF-8”?</span>>
< <span style="color:#3f7f7f">beans </span> <span style="color:#7f007f">xmlns</span> = <span style="color:#2a00ff">“http://www.springframework.org/schema/beans” </span>
       <span style="color:#7f007f">xmlns:xsi</span> = <span style="color:#2a00ff">“http://www.w3.org/2001/XMLSchema-instance” </span>
       <span style="color:#7f007f">xmlns:aop</span> = <span style="color:#2a00ff">“http:// www .springframework.org / schema / aop“ </span>
       <span style="color:#7f007f">xsi:schemaLocation</span> = <span style="color:#2a00ff">”http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd“</span> >

    < <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“org.springframework.beans.factory.config.CustomScopeConfigurer”</span> >
        < <span style="color:#3f7f7f">property </span> <span style="color:#7f007f">name</span> = <span style="color:#2a00ff">“scopes”</span> >
            < <span style="color:#3f7f7f">map</span> >
                < <span style="color:#3f7f7f">entry </span> <span style="color:#7f007f">key</span> = <span style="color:#2a00ff">“thread”</span> >
                    < <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“com.foo.ThreadScope”</span> />
                < <span style="color:#3f7f7f">/ entry</span> >
            < <span style="color:#3f7f7f">/ map</span> >
        < <span style="color:#3f7f7f">/ property</span> >
    < <span style="color:#3f7f7f">/ bean</span> >

    < <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“bar” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“xyBar” </span> <span style="color:#7f007f">scope</span> = <span style="color:#2a00ff">“thread”</span> >
        < <span style="color:#3f7f7f">property </span> <span style="color:#7f007f">name</span> = <span style="color:#2a00ff">“name” </span> <span style="color:#7f007f">value</span> = <span style="color:#2a00ff">“Rick”</span> />
        < <span style="color:#3f7f7f">aop:scoped-proxy</span> />
    < <span style="color:#3f7f7f">/ bean</span> >

    < <span style="color:#3f7f7f">bean </span> <span style="color:#7f007f">id</span> = <span style="color:#2a00ff">“foo” </span> <span style="color:#7f007f">class</span> = <span style="color:#2a00ff">“xyFoo”</span> >
        < <span style="color:#3f7f7f">property </span> <span style="color:#7f007f">name</span> = <span style="color:#2a00ff">“bar” </span> <span style="color:#7f007f">ref</span> = <span style="color:#2a00ff">“bar”</span> />
    < <span style="color:#3f7f7f">/ bean</span> >

< <span style="color:#3f7f7f">/ beans</span> ></span></span>

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值