每个Bean都有自己的作用域,它们会在特定的时间生成,在特定的范围生存。Spring IOC容器的bean有四种作用域:

其中默认的作用域是singleton,单例模式。也就是我们之前配置的bean的作用域模式,即所有的bean只有一个,并且在一开始就生成了。
prototype则是在每次getBean的时候都会生成一个新的实例。
request则是以每次请求作用作用域,session则是Http Session被创建的时候被创建的,并且作用域适用于WebApplicationContext环境。
好,我们今天主要看看前两者:
我们先将CarBean定义给出,这里我们在构造方法里加入了控制台输出信息。
1package com.happyBKs.autowire; 2 3public class CarBean { 4 String brand; 5 double price; 6 public String getBrand() { 7 return brand; 8 } 9 public void setBrand(String brand) { 10 this.brand = brand; 11 } 12 public double getPrice() { 13 return price; 14 } 15 public void setPrice(double price) { 16 this.price = price; 17 } 18 public CarBean(String brand, double price) { 19 super(); 20 this.brand = brand; 21 this.price = price; 22 } 23 public CarBean() { 24 super(); 25 System.out.println(this.brand+" Constructor ...."); 26 } 27 @Override 28 public String toString() { 29 return "CarBean [brand=" + brand + ", price=" + price + "]"; 30 } 31 32}
IOC容器配置:\src\main\resources\bean-scopes.xml
1<?xml version="1.0" encoding="UTF-8"?> 2<beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 5 6 <bean id="carBM" class="com.happyBKs.autowire.CarBean" p:brand="BM" 7 p:price="400000" scope="singleton" /> 8 <bean id="carAudi" class="com.happyBKs.autowire.CarBean" p:brand="Audi" 9 p:price="300000" scope="prototype" /> 10 11</beans>
测试代码:
1@Test 2 public void testScope1() { 3 4 { 5 System.out.println("example 1:"); 6 ApplicationContext ac = new ClassPathXmlApplicationContext("bean-scopes.xml"); 7 System.out.println("getBean(carBM)"); 8 CarBean cb = (CarBean) ac.getBean("carBM"); 9 System.out.println(cb); 10 } 11 12 { 13 System.out.println("example 2:"); 14 ApplicationContext ac = new ClassPathXmlApplicationContext("bean-scopes.xml"); 15 System.out.println("getBean(carAudi)"); 16 CarBean cb = (CarBean) ac.getBean("carAudi"); 17 System.out.println(cb); 18 } 19 }
输出结果:
example 1:
七月 18, 2015 10:32:13 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@191d7bd5: startup date [Sat Jul 18 22:32:13 CST 2015]; root of context hierarchy
七月 18, 2015 10:32:13 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [bean-scopes.xml]
null Constructor ....
getBean(carBM)
CarBean [brand=BM, price=400000.0]
example 2:
七月 18, 2015 10:32:14 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3e9c00ea: startup date [Sat Jul 18 22:32:14 CST 2015]; root of context hierarchy
七月 18, 2015 10:32:14 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [bean-scopes.xml]
null Constructor ....
getBean(carAudi)
null Constructor ....
CarBean [brand=Audi, price=300000.0]
注意了,第二个例子中有两个null Constructor ....
第一个是carBM在加载IOC容器配置文件时自动加载的,因为那个bean是singleton的作用域,即使不使用它,也会被构造。
第二个是在getBean时加载的,只有需要时才会被构造。
那么你也许会问?真的是重新被构造了吗?我再给例子吧。
我们分别用同一个容器,getBean两次,看看singleton和protoType作用域下返回对象的区别:
singleton
1@Test 2 public void testScope2() { 3 4 5 6 ApplicationContext ac1 = new ClassPathXmlApplicationContext( 7 "bean-scopes.xml"); 8 CarBean cb1 = (CarBean) ac1.getBean("carBM"); 9 System.out.println(cb1); 10 11 CarBean cb2 = (CarBean) ac1.getBean("carBM"); 12 System.out.println(cb2); 13 14 if(cb1==cb2) 15 { 16 System.out.println("the same one!"); 17 } 18 else 19 { 20 System.out.println("different!"); 21 } 22 23 24 }
输出:
七月 18, 2015 10:45:24 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@75e81ab3: startup date [Sat Jul 18 22:45:24 CST 2015]; root of context hierarchy
七月 18, 2015 10:45:24 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [bean-scopes.xml]
null Constructor ....
CarBean [brand=BM, price=400000.0]
CarBean [brand=BM, price=400000.0]
the same one!
protoType
1@Test 2 public void testScope3() { 3 4 5 6 ApplicationContext ac1 = new ClassPathXmlApplicationContext( 7 "bean-scopes.xml"); 8 CarBean cb1 = (CarBean) ac1.getBean("carAudi"); 9 System.out.println(cb1); 10 11 12 CarBean cb2 = (CarBean) ac1.getBean("carAudi"); 13 System.out.println(cb2); 14 15 if(cb1==cb2) 16 { 17 System.out.println("the same one!"); 18 } 19 else 20 { 21 System.out.println("different!"); 22 } 23 24 25 }
输出结果:
七月 18, 2015 10:46:12 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@72f9ebcd: startup date [Sat Jul 18 22:46:12 CST 2015]; root of context hierarchy
七月 18, 2015 10:46:12 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [bean-scopes.xml]
null Constructor ....
null Constructor ....
CarBean [brand=Audi, price=300000.0]
null Constructor ....
CarBean [brand=Audi, price=300000.0]
different!
但是,请注意,如果是不同的ApplicationContext,也就是两个不同的容器,那么无论什么作用域类型,返回的对象一定不是同一个。