spring Bean范围

网友投稿 282 2022-12-01

spring Bean范围

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

您不仅可以控制要插入到从特定bean定义创建的对象中的各种依赖项和配置值,还可以控制从特定bean定义创建的对象的范围。这种方法功能强大且灵活,因为您可以选择通过配置创建的对象的范围,而不必在Java类级别烘焙对象的范围。可以将Bean定义为部署在多个范围之一中。Spring Framework支持六个范围,其中四个范围仅在您使用Web感知时才可用​​ApplicationContext​​​。您还可以创建 自定义范围​​。​​

下表描述了支持的范围:

范围

描述

独生子

(默认)将单个bean定义范围限定为每个Spring IoC容器的单个对象实例。

原型

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

请求

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

会议

将单个bean定义范围限定为HTTP的生命周期​​Session​​​。仅在具有Web感知功能的Spring环境中有效​​ApplicationContext​​。

应用

将单个bean定义范围限定为a的生命周期​​ServletContext​​​。仅在具有Web感知功能的Spring环境中有效​​ApplicationContext​​。

WebSocket

将单个bean定义范围限定为a的生命周期​​WebSocket​​​。仅在具有Web感知功能的Spring环境中有效​​ApplicationContext​​。

单身范围

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

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

Spring的单例bean概念不同于Gang of Four(GoF)模式书中定义的单例模式。GoF单例对一个对象的范围进行硬编码,使得每个ClassLoader创建一个且只有一个特定类的实例。Spring单例的范围最好描述为每容器和每个bean。这意味着,如果在单个Spring容器中为特定类定义一个bean,则Spring容器将创建该bean定义所定义的类的一个且仅一个实例。单例范围是Spring中的默认范围。要将bean定义为XML中的单例,您可以定义一个bean,如以下示例所示:

原型范围

bean部署的非单例原型范围导致每次发出对该特定bean的请求时都创建新的bean实例。也就是说,bean被注入另一个bean,或者通过​​getBean()​​对容器的方法调用来请求它。通常,您应该对所有有状态bean使用原型范围,对无状态bean使用单例范围。

下图说明了Spring原型范围:

(数据访问对象(DAO)通常不配置为原型,因为典型的DAO不会保持任何会话状态。我们更容易重用单例图的核心。)

以下示例将bean定义为XML中的原型:

与其他范围相比,Spring不管理原型bean的完整生命周期。容器实例化,配置和组装原型对象并将其交给客户端,而没有该原型实例的进一步记录。因此,尽管无论范围如何都在所有对象上调用初始化生命周期回调方法,但在原型的情况下,不会调用已配置的销毁生命周期回调。客户端代码必须清理原型范围的对象并释放原型bean所拥有的昂贵资源。要使Spring容器释放原型范围的bean所拥有的资源,请尝试使用自定义bean后处理器,它包含对需要清理的bean的引用。

在某些方面,Spring容器关于原型范围bean的角色是Java ​​new​​运算符的替代品。超过该点的所有生命周期管理必须由客户端处理。(有关Spring容器中bean的生命周期的详细信息)

自定义范围

bean范围机制是可扩展的。您可以定义自己的范围,甚至可以重新定义现有范围,尽管后者被认为是不好的做法,您无法覆盖内置​​singleton​​​和​​prototype​​范围。

创建自定义范围

要将自定义作用域集成到Spring容器中,需要实现​​org.springframework.beans.factory.config.Scope​​​本节中描述的 接口。有关如何实现自己的作用域的想法,请参阅​​Scope​​​ Spring Framework本身和​​Scope​​javadoc 提供的实现 ,它们解释了您需要更详细地实现的方法。

该​​Scope​​接口有四种方法可以从作用域中获取对象,将其从作用域中删除,然后将其销毁。

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

Object get(String name, ObjectFactory objectFactory)

例如,会话范围实现从基础会话中删除会话范围的bean。应返回该对象,但如果找不到具有指定名称的对象,则可以返回null。以下方法从基础范围中删除对象:

Object remove(String name)

以下方法记录范围在销毁时或范围中指定对象被销毁时应执行的回调:

void registerDestructionCallback(String name, Runnable destructionCallback)

有关 销毁回调的更多信息,请参阅​​j​​avadoc或Spring作用域实现。

以下方法获取基础范围的对话标识符:

String getConversationId()

每个范围的标识符都不同。对于会话范围的实现,该标识符可以是会话标识符。

使用自定义范围

在编写并测试一个或多个自定义​​Scope​​​实现之后,需要让Spring容器知道您的新范围。以下方法是​​Scope​​使用Spring容器注册new的核心方法:

void registerScope(String scopeName, Scope scope);

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

假设您编写自定义​​Scope​​实现,然后注册它,如下一个示例所示。

 

下一个示例使用​​SimpleThreadScope​​​,它包含在Spring中,但默认情况下未注册。您自己的自定义​​Scope​​ 实现的说明是相同的。

Scope threadScope = new SimpleThreadScope();beanFactory.registerScope("thread", threadScope);

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

 

放置​​<aop:scoped-proxy/>​​​在​​FactoryBean​​​实现中时,工厂bean本身是作用域的,而不是从中返回的对象​​getObject()​​。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:开放平台应用安全开发指南
下一篇:IDEA 2021.2 激活教程及启动报错问题解决方法
相关文章

 发表评论

暂时没有评论,来抢沙发吧~