默认情况下,注入到IOC容器中的bean都是单例的,当从容器中多次获取bean时,获取到的都是同一个bean的对象。因为,在bean注入到IOC容器中时,scope属性默认为singleton的,即单例的,同时,scope还可以指定prototype、request、session类型的。
【一】XML的配置形式
1、singleton类型的
<!--scope="singleton"属性指定注入的bean为单例的-->
<bean id="car" class="com.lzj.spring.Car" scope="singleton">
<property name="brand" value="baoma"></property>
<property name="price" value="100000"></property>
</bean>
当从容器中获取bean时,
ClassPathXmlApplicationContext ctx =
new ClassPathXmlApplicationContext("bean.xml");
Car car = (Car) ctx.getBean("car");
Car car2 = (Car) ctx.getBean("car");
获取到的car对象和car2对象是同一个对象。该对象在容器初始化时就自动创建了(执行了Car的构造函数)。
2、prototype类型的
<!--scope="prototype"属性指定注入的bean为原型的-->
<bean id="car" class="com.lzj.spring.Car" scope="prototype">
<property name="brand" value="baoma"></property>
<property name="price" value="100000"></property>
</bean>
当从容器中获取bean时,
ClassPathXmlApplicationContext ctx =
new ClassPathXmlApplicationContext("bean.xml");
Car car = (Car) ctx.getBean("car");
Car car2 = (Car) ctx.getBean("car");
获取到car对象和car2对象不是一个对象,是同一个java bean的两个实现对象。
未完。。。
【二】、注解的形式配置
一、Bean的单例作用域
众所周知,spring容器中的Bean默认是单例(Singleton)的,任何一个类在容器中只创建一个实例的Bean。下面用代码演示
1、创建应用类
该应用类中只有一个方法,每次调用该方法,就对变量i执行加1的操作。
package com.spring.prototype;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component("gernarate")
public class GernerateNumber {
private int i=0;
//生成从1到n的数
public void generate() {
i = i + 1;
System.out.println("我是:" + i);
}
}
2、创建配置类
该配置类中没有实现其它逻辑,只是为了获取容器中的Bean的目的。
package com.spring.prototype;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//配置类
@Configuration
@ComponentScan
public class AnnotationConfig {
}
3、创建测试类
创建测试类,从容器中连续获取5次名字为“gernarate”的Bean,发现每次获取的都是同一个Bean。
package com.spring.prototype;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AnnotationConfig.class);
for(int i=0; i<5; i++){
GernerateNumber gernerator = (GernerateNumber) ctx.getBean("gernarate");
gernerator.generate();
}
}
}
输出结果为:
我是:1
我是:2
我是:3
我是:4
我是:5
从输出结果可以看出,每次获取的Bean都是同一个Bean。
二、Bean的原型作用域
假设一个容器中的Bean注入到一个引用变量中,然后执行了一系列操作,该Bean的实例中变量已经改变。但是另一个引用变量也想引用该Bean未被污染的实例,此时就不能再用默认的单例模式了,而要用原型(Prototype)模式。代码演示
上面的应配置类和测试类均不变,只改变应用类,只是在创建类的时候加上了注解@Scope(“prototype”),如果不加,默认是@Scope(“Singleton”)的。如下:
package com.spring.prototype;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component("gernarate")
@Scope("prototype")
public class GernerateNumber {
private int i=0;
//生成从1到n的数
public void generate() {
i = i + 1;
System.out.println("我是:" + i);
}
}
测试输出为:
我是:1
我是:1
我是:1
我是:1
我是:1
从测试结果可以看出,每次获取名字为“gernarate”的Bean时,都生成一个新的实例,摆脱了单例模式。另外容器中还支持会话(Session) 和请求(Rquest),等到web时再继续更新。