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

其中默认的作用域是singleton,单例模式。也就是我们之前配置的bean的作用域模式,即所有的bean只有一个,并且在一开始就生成了。
prototype则是在每次getBean的时候都会生成一个新的实例。
request则是以每次请求作用作用域,session则是Http Session被创建的时候被创建的,并且作用域适用于WebApplicationContext环境。
好,我们今天主要看看前两者:
我们先将CarBean定义给出,这里我们在构造方法里加入了控制台输出信息。
package com.happyBKs.autowire;
public class CarBean {
    String brand;
    double price;
    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public CarBean(String brand, double price) {
        super();
        this.brand = brand;
        this.price = price;
    }
    public CarBean() {
        super();
        System.out.println(this.brand+" Constructor ....");
    }
    @Override
    public String toString() {
        return "CarBean [brand=" + brand + ", price=" + price + "]";
    }
    
}
IOC容器配置:\src\main\resources\bean-scopes.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="carBM" class="com.happyBKs.autowire.CarBean" p:brand="BM"
        p:price="400000" scope="singleton" />
    <bean id="carAudi" class="com.happyBKs.autowire.CarBean" p:brand="Audi"
        p:price="300000" scope="prototype" />
</beans>
测试代码:
@Test
    public void testScope1() {
        
        {
            System.out.println("example 1:");
            ApplicationContext ac = new ClassPathXmlApplicationContext("bean-scopes.xml");
            System.out.println("getBean(carBM)");
            CarBean cb = (CarBean) ac.getBean("carBM");
            System.out.println(cb);
        }
    
        {
            System.out.println("example 2:");
            ApplicationContext ac = new ClassPathXmlApplicationContext("bean-scopes.xml");
            System.out.println("getBean(carAudi)");
            CarBean cb = (CarBean) ac.getBean("carAudi");
            System.out.println(cb);
        }
    }
输出结果:
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
@Test
    public void testScope2() {
        
        
        
        ApplicationContext ac1 = new ClassPathXmlApplicationContext(
                "bean-scopes.xml");
        CarBean cb1 = (CarBean) ac1.getBean("carBM");
        System.out.println(cb1);
        
        CarBean cb2 = (CarBean) ac1.getBean("carBM");
        System.out.println(cb2);
        
        if(cb1==cb2)
        {
            System.out.println("the same one!");
        }
        else
        {
            System.out.println("different!");
        }
        
    }
输出:
七月 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
@Test
    public void testScope3() {
        
        
        
        ApplicationContext ac1 = new ClassPathXmlApplicationContext(
                "bean-scopes.xml");
        CarBean cb1 = (CarBean) ac1.getBean("carAudi");
        System.out.println(cb1);
        
        CarBean cb2 = (CarBean) ac1.getBean("carAudi");
        System.out.println(cb2);
        
        if(cb1==cb2)
        {
            System.out.println("the same one!");
        }
        else
        {
            System.out.println("different!");
        }
        
    }
输出结果:
七月 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,也就是两个不同的容器,那么无论什么作用域类型,返回的对象一定不是同一个。
 
  
  
  
 
 
  
 
 
 