创建 BeanDefinition 时,就等于创建了一个配方,用于创建由 BeanDefinition 所定义的类实例。BeanDefinition 是配方的这种思想很重要,因为这意味着,与使用类一样,也可通过一个配方创建多个对象实例。
有如下优点:
可以控制要插入到从特定 BeanDefinition 创建的对象中的各种依赖项和配置值
可以控制从特定 BeanDefinition 创建的对象的作用域。
这种方式功能强大且灵活,因为开发者可以选择通过配置创建的对象的作用域,而不必在Java类级别上考虑对象的范围。
Spring 支持哪些作用域呢?
Spring支持如下六种作用域,其中四种只有在使用可识别Web的 ApplicationContext 时才可用。
| 作用域 | 描述 |
| singleton |
当然了,作为灵活的框架,Spring 还允许开发者创建自定义的作用域。
详细介绍下 singleton 作用域?
仅管理一个singleton bean的一个共享实例,并且所有对具有ID或与该 BeanDefinition 相匹配的ID的bean的请求都将导致该特定的bean实例由Spring容器返回。
换言之,当我们定义了一个 BeanDefinition 并且其作用域为 singleton 时,IoC容器将为该 BeanDefinition 所定义的对象创建一个实例。该单实例存储在此类单例bean的缓存中,并且对该命名bean的所有后续请求和引用都返回该缓存的对象。
和单例模式有何联系去区别呢?
Spring的 singleton bean概念与传说中的四人帮创建的《Gang of Four (GoF) patterns》一书中定义的单例模式并不一样。
GoF的单例模式会硬编码对象的作用域,使得每个类加载器只能创建一个特定类的唯一实例
因此,最恰当的应该将Spring单例的作用域描述为一个容器对应一个bean。若我们在单个Spring容器中为特定类定义一个bean,则Spring容器将创建该 BeanDefinition 所定义的类的一个且只有一个实例。
单例作用域是Spring中的默认作用域。要将bean定义为XML中的单例,可以定义bean,如以下示例所示:
Prototype作用域
Bean部署的非单一原型作用域会在每次请求特定bean时创建一个新bean实例。也就是说,该Bean被注入到另一个Bean中,或者您可以通过容器上的getBean()方法调用来请求它。通常,应将原型作用域用于所有有状态Bean,将单例作用域用于无状态Bean。
下图说明了Spring原型范围
前言
在 Spring 中,那些组成应用程序的主体及由 Spring IOC 容器所管理的对象,被称之为 bean。
简单地讲,bean 就是由 IOC 容器初始化、装配及管理的对象,除此之外,bean 就与应用程序中的其他对象没有什么区别了。
而 bean 的定义以及 bean 相互间的依赖关系将通过配置元数据来描述。
Spring中的bean默认都是单例的,这些单例Bean在多线程程序下如何保证线程安全呢?
例如对于Web应用来说,Web容器对于每个用户请求都创建一个单独的Sevlet线程来处理请求,引入Spring框架之后,每个Action都是单例的,那么对于Spring托管的单例Service Bean,如何保证其安全呢?
Spring的单例是基于BeanFactory也就是Spring容器的,单例Bean在此容器内只有一个
Java的单例是基于 JVM,每个 JVM 内只有一个实例
1 bean的作用域
创建一个bean定义,其实质是用该bean定义对应的类来创建真正实例的“配方”。
把bean定义看成一个配方很有意义,它与class很类似,只根据一张“处方”就可以创建多个实例。
不仅可以控制注入到对象中的各种依赖和配置值,还可以控制该对象的作用域。
这样可以灵活选择所建对象的作用域,而不必在Java Class级定义作用域。
- Spring Framework支持五种作用域,分别阐述如下表。
五种作用域中,request、session 和 global session 三种作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于 web 的 Spring ApplicationContext 环境。
2 singleton —— 唯一 bean 实例
当一个 bean 的作用域为 singleton,那么Spring IoC容器中只会存在一个共享的 bean 实例,并且所有对 bean 的请求,只要 id 与该 bean 定义相匹配,则只会返回bean的同一实例。
singleton 是单例类型(对应于单例模式),就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,但我们可以指定Bean节点的 lazy-init=”true” 来延迟初始化bean,这时候,只有在第一次获取bean时才会初始化bean,即第一次请求该bean时才初始化。
每次获取到的对象都是同一个对象。注意,singleton 作用域是Spring中的缺省作用域。要在XML中将 bean 定义成 singleton ,可以这样配置:
<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">
也可以通过 @Scope 注解(它可以显示指定bean的作用范围。)的方式
@Service @Scope("singleton") public class ServiceImpl{ }
3 prototype——每次请求都会创建一个新的 bean 实例
当一个bean的作用域为 prototype,表示一个 bean 定义对应多个对象实例。
prototype 作用域的 bean 会导致在每次对该 bean 请求(将其注入到另一个 bean 中,或者以程序的方式调用容器的 getBean() 方法)时都会创建一个新的 bean 实例。prototype 是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。
对有状态的 bean 应该使用 prototype 作用域,而对无状态的 bean 则应该使用 singleton 作用域。
在 XML 中将 bean 定义成 prototype
<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/> 或者 <bean id="account" class="com.foo.DefaultAccount" singleton="false"/>
通过 @Scope 注解的方式实现就不做演示了。

