1. singleton
配置中的bean定义可以看作是一个模板,容器会根据这个模板来构造对象。bean定义中的scope语义会决定:容器将根据这个模板构造多少对象实例,又该让这个对象实例存活多久。标记为拥有singleton scope的对象定义,在Spring的IoC容器中只存在一个对象实例,所有该对象的引用都共享这个实例。该实例从容器启动,并因为第一次被请求而初始化之后,将一直存活到容器退出,也就是说,它与IoC容器“几乎”拥有相同的“寿命”。
下图是Spring参考文档中给出的singleton的bean的实例化和注入语义示意图,或许更能形象得说明问题。
[img]http://upload-images.jianshu.io/upload_images/44770-11a5a1a494209fff.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240[/img]

Spring中的bean默认是singleton的,下面这两种写法的效果相同:


<bean id="accountService" class="com.foo.DefaultAccountService"/>
<!-- the following is equivalent, though redundant (singleton scope is the default) -->
<bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/>

代码说明:

public class CustomerService 
{
String message;

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}
}



<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean id="customerService"
class="com.mkyong.customer.services.CustomerService" />

</beans>

public static void main( String[] args )
{
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"Spring-Customer.xml"});

CustomerService custA = (CustomerService)context.getBean("customerService");
custA.setMessage("Message by custA");
System.out.println("Message : " + custA.getMessage());


CustomerService custB = (CustomerService)context.getBean("customerService");
System.out.println("Message : " + custB.getMessage());
}



则输出结果都是一样的:


Message : Message by custA


Message : Message by custA



这里由于默认是单例,只要从容器中取,其实都是其中的同一个实例



2)prototype


针对声明为拥有prototype scope的bean定义,容器在接到该类型对象的请求的时候,会每次都重新生成一个新的实例对象给请求方。虽然这种类型的对象的实例化以及属性设置等工作都是由容器负责的,但是只要准备完毕,并且对象实例返回请求方之后,容器就不再拥有当前返回对象的引用,请求方需要自己负责当前返回对象的后继的声明周期的管理工作,例如该对象的销毁。也就是说,容器每次返回给请求方一个新的实例对象后,就任由这个对象“自生自灭”了。


对于那些请求方不能共享使用的对象类型,应该将其bean定义的scope设置为prototype。这样,每个请求方可以得到自己专有的一个对象实例。通常,声明为prototype的对象都是一些有状态的,比如保存每个顾客信息的对象。


从Spring参考文档下的这幅图片,可以再次了解prototype scope的bean定义,在实例化对象和注入依赖的时候,它的具体语义是什么样子。


[img]


​http://upload-images.jianshu.io/upload_images/44770-6e4899d92cda505a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 ​​[/img]



用以下两个ban定义的效果是一样的:



<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/>


<bean id="accountService" class="com.foo.DefaultAccountService" singleton="false"/>




代码讲解,同样上面的例子:


Message : Message by custA
Message : null



在prototype中,每次调用getbean,都生成新的实例