singleton:(默认)作用域为每个springIOC容器的单个对象实例定义单个bean
prototype:将单个bean定义为任意数量的对象实例
(1)单例的作用域
容器只管理【一个bean的共享实例】,所有对具有一个或多个标识符的bean的请求都将导致Spring容器返回一个特定唯一的bean实例。
换句话说,当您定义一个beanDifination并且它的作用域为单例时,Spring IoC容器会创建由该beanDifination定义的对象的一个实例。 这个实例对象会存储单例bean的缓存中,对该命名bean的所有后续请求和引用都会返回缓存的对象。 下面的图片展示了单例作用域是如何工作的:
(2)原型作用域
非单例原型作用域导致【每次对特定bean发出请求时都要创建一个新的bean实例】。 也就是说,该bean被注入到另一个bean中,或者您通过容器上的getBean()
方法调用请求它,都会创建一个新的bean。 作为一条规则,您应该对所有有状态bean使用原型作用域,对无状态bean使用单例作用域。
下图说明了Spring原型的作用域:
下面的示例用XML将beanDifination为原型:
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
与其他作用域相比,Spring并【不管理原型bean的完整生命周期】。 容器实例化、配置和组装一个原型对象,并将其传递给客户端,而不需要进一步记录该原型实例,不会缓存,不会管理他的后续生命周期。 因此,尽管初始化生命周期回调方法在所有对象上都被调用但在原型的情况下,配置的销毁生命周期回调不会被调用
在某些方面,Spring容器在原型作用域bean中的角色是Java【new】操作符的替代。 超过这一点的所有生命周期管理都必须由客户端处理。
(3)会话、应用和WebSocket作用域
【request 】,【session 】, 【application】和【websocket 】作用域只有在你使用web项目中的Spring【ApplicationContext】实现(如XmlWebApplicationContext)时才可用。 如果您将这些作用域与常规Spring IoC容器一起使用,例如“ClassPathXmlApplicationContext”,则会抛出一个“IllegalStateException”,该异常会告知一个未知的bean作用域。
(4)自定义范围
bean作用域机制是可扩展的,您可以定义自己的作用域,甚至可以重新定义现有的作用域,尽管后者被认为是不好的做法,而且您不能覆盖内置的' singleton '和' prototype '作用域