Spring 5 中文解析核心篇-IoC容器之Bean作用域
当你创建一个的定义时候,你可以创建一个模版(recipe)通过定义的类定义去创建一个真实的实例。定义是模版(recipe)的概念很重要,因为这意味着,与使用类一样,你可以从一个模版(recipe)创建多个对象实例。
你不仅可以控制要插入到从特定定义创建的对象中的各种依赖项和配置值,还可以控制从特定定义创建的对象的作用域。这种方法是非常有用的和灵活的,因为你可以选择通过配置创建的对象的作用域,而不必在Java类级别上考虑对象的作用域。能够定义部署到一个或多个作用域。框架支撑6种作用域,4种仅仅使用环境。你可以创建定制的作用域。
下面的表格描述了支撑的作用域:

从后,线程安全作用域是有效的但默认没有注册。更多的信息,查看文档 。更多关于怎样去注册和自定义作用域,查看
1.5.1 单例bean作用域
单例仅仅只有一个共享实例被容器管理,并且所有对具有与该定义相匹配的的的请求都会导致该特定实例被容器返回。换一种方式,当你定义一个的定义并且它的作用域是单例的时候,容器创建通过定义的对象定义的实例。这个单例存储在缓存中,并且对命名的所有请求和引用返回的是缓存对象。下面图片展示了单例作用域是怎样工作的:

的单例概念与在设计模式书中的单例模式不同。单例硬编码对应的作用域例如:只有一个特定类的对象实例对每一个只创建一个对象实例。最好将单例的范围描述为每个容器和每个(备注:设计模式中的单例是针对不同来说的,而的单例是针对不同容器级别的)。这意味着,如果在单个容器对指定类定义一个,容器通过定义的类创建一个实例。在中单例作用域是默认的。在XML中去定义一个为单例,你可以定义一个类似下面例子:
1.5.2 原型作用域
非单例原型的作用域部署结果是在每一次请求指定的时候都会创建一个实例。也就是,被注入到其他或在容器通过方法调用都会创建一个新。通常,为所有的无状态bean使用原型作用域并且有状态使用单例作用域。
下面的图说明的单例作用域:

数据访问对象()通常不被配置作为一个原型,因为典型的不会维持任何会话状态。我们可以更容易地重用单例图的核心。
下面例子在中定义一个原型:
与其他作用域对比,没有管理原型的完整生命周期。容器将实例化、配置或以其他方式组装原型对象,然后将其交给客户端,无需对该原型实例的进一步记录。因此,尽管初始化生命周期回调函数在所有对象上被回调而不管作用域如何,在原型情况下,配置销毁生命周期回调是不被回调。客户端代码必须清除原型作用域内的对象并释放原型占用的昂贵资源。为了让容器释放原型作用域所拥有的资源,请尝试使用自定义的后置处理器,该后处理器包含对需要清理的的引用(可以通过后置处理器释放引用资源)。
在某些方面,容器在原型范围内的角色是运算符的替代。所有超过该点的生命周期管理都必须由客户端处理。(更多关于在容器中的生命周期,查看)
1.5.3 单例bean与原型bean的依赖
当你使用依赖于原型的单例作用域时(单例引用原型),需要注意的是这些依赖项在初始化时候被解析。因此,如果你依赖注入一个原型到一个单例中,一个新原型被初始化并且依赖注入到一个单例。原型实例是唯一一个被提供给单例作用域的实例。(备注:单例引用原型bean时原型bean只会有一个)
然而,假设你希望单例作用域在运行时重复获取原型作用域的一个新实例。你不能依赖注入一个原型到一个单例,因为注入只发生一次,当容器实例化单例、解析和注入它的依赖时。如果在运行时不止一次需要原型的新实例,查看
1.5.4 Request, Session, Application, and WebSocket Scopes
、、、和作用域仅仅在你使用 的实现(例如:)时有效。如果你将这些作用域与常规的容器(例如)一起使用,则会抛出一个异常,该错抛出未知的作用域。
初始化Web配置
作用域
Session作用域
Application作用域
作用域bean作为依赖项
在前面的例子中,单例bean () 被注入一个引用到 作用域的 ()。这个显著点是 bean是一个单例bean:这个实例在每个容器值初始化一次,并且它的依赖(在这个例子仅仅一个, bean)仅仅被注入一次。这意味着 bean运行仅仅在相同的对象上(也就是,最初注入的那个)。
当注入一个短生命周期作用域的到一个长生命周期作用域的时候这个不是我们期望的方式(例如:注入一个HTTP 作用域的协同者作为一个依赖注入到单例)。相反,你只需要一个对象,并且在会话的生存期内,你需要一个特定于HTTP会话的对象。因此,容器创建一个对象,该对象公开与类完全相同的公共接口(理想地,对象是实例),可以从作用域机制(HTTP 请求,,以此类推)获取真正的对象。容器注入这个代理对象到 bean,这并不知道此引用是代理。在这个例子中,当实例调用在依赖注入对象上的方法时,它实际上是在代理上调用方法。然后代理从(在本例中)会话中获取实际的对象,并将方法调用委托给检索到的实际对象。
因此,在将和的bean注入到协作对象中时,你需要以下(正确和完整)配置,如以下示例所示:
代理类型选择
1.5.5 自定义作用域
作用域机制是可扩展的。你可以定义你自己的作用域或者甚至重定义存在的作用域,尽管后者被认为是不好的做法,你不能覆盖内置的单例和原型范围。
创建一个自定义作用域
使用自定义作用域
作者
个人从事金融行业,就职过易极付、思建科技、某网约车平台等重庆一流技术团队,目前就职于某银行负责统一支付系统建设。自身对金融行业有强烈的爱好。同时也实践大数据、数据存储、自动化集成和部署、分布式微服务、响应式编程、人工智能等领域。同时也热衷于技术分享创立公众号和博客站点对知识体系进行分享。
微信公众号:
