spring bean作用域 (一)

Spring 的 Scope大概有五种形式,分别是:

1.Singleton:在Spring Ioc容器中仅存在一个Bean实例,Bean以单实例形式存在。Singleton是Spring的默认配置。

2.Prototype:每次从容器中调用Ben时,都返回一个新的实例。每次调用AnnotationConfigApplicationContext的getBean()方法时,都等价于执行了一次newXxxBean()方法。

3.request:Web项目中,给每一个http request新建一个Bean。

4.session:Web项目中,给每一个http session新建一个Bean。

5.GlobalSession:同一个全局Session共享一个Bean,一般用于Portlet应用环境。

3,4,5仅适应于WebApplicationContext环境中。

今天主要说的是前两种,Singleton和Prototype,即单例模式和多例模式。

Singleton:

Singleton的Bean在同一个Spring Ioc容器中只存在一个实例。

这个例子是在《精通spring 4.x》上看到的,觉得很形象

    //1
    //2
    //3
    //4
我们在1处把car声明为singleton实例,这个地方也可不写,因为spring的默认状态就是singleton模式,然后我们声明了三个bean,2,3,4。这三个Ben的car属性都是指向同一个Bean(car)的,如图:

spring bean作用域 (一)_第1张图片

在默认情况下,在启动容器AnnotationConfigApplicationContext的时候就会初始化这些singleton的bean,这样做是有很大的好处的。虽然在启动容器的时候要加载大量的bean,浪费一些时间,但是在这个过程中可以发现一些不容易发现的配置问题,还有一点就是这些bean以缓存的形式被保存起来了,当程序运行到需要到他们的地方,不需要再初始化了,提高了运行效率。

刚才提到了,spring在启动的时候便会初始化这些singleton类型的bean,但是并不是每个用户都希望这样,所有spring提供了延迟加载控制:

id="boss2" class="com.smart.scope.Boss" p: car-ref="car" lazy-init="">
但是这个设置不是绝对的,如果这个bean被提前实例化的bean引用了,那么spring就会忽略这个设置。


prototype

同样的例子,

    //1
    //2
    //3
    //4
在这个配置里面把car定义成prototype,所有每一个boss在调用getBean(Car.class)的时候都会得到一个新的car实例,如图:

spring bean作用域 (一)_第2张图片
spring Ioc容器在启动时不会实例化prototype的Bean,当spring Ioc把prototype的Bean交给调用者以后,就不在关心它的生命周期了。


看一个简单的例子:

1.编写singleton的Bean

@Service
public class DemoSingletonService {
}
2.编写prototype的Bean

@Service
@Scope("prototype")
public class DemoPrototypeService {
}
3.配置类

@Configuration
@ComponentScan("com.example.ch2.scope")
public class ScopeConfig {
}
4.运行主函数类

public class Main {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(ScopeConfig.class);
        DemoSingletonService s1=context.getBean(DemoSingletonService.class);
        DemoSingletonService s2=context.getBean(DemoSingletonService.class);

        DemoPrototypeService d1=context.getBean(DemoPrototypeService.class);
        DemoPrototypeService d2=context.getBean(DemoPrototypeService.class);

        System.out.println("s1==s2 ?  "+s1.equals(s2));
        System.out.println("d1==d2 ?  "+d1.equals(d2));
    }
}
看一下输出结果:

spring bean作用域 (一)_第3张图片



参考《精通spring 4》《springboot 实战》

你可能感兴趣的:(Spring)