Spring中单例模式中的饿汉和懒汉以及Spring中的多例模式

链接:https://pan.baidu.com/s/1wgxnXnGbPdK1YaZvhO7PDQ
提取码:opjr

单例模式:每个bean定义只生成一个对象实例,每次getBean请求获得的都是此实例

单例模式分为饿汉模式和懒汉模式

饿汉模式:spring singleton的缺省是饿汉模式:启动容器时(即实例化容器时),为所有spring配置文件中定义的bean都生成一个实例

懒汉模式:在第一个请求时才生成一个实例,以后的请求都调用这个实例

在网上有许多这样的概念,你也一定烦了吧,我们用代码来看清楚这个过程

为了展示过程,我们需要引入log4j的jar包,把过程打印在控制台中

BigKingTest类中的代码如下:

 1 package top.bigking.test;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 import top.bigking.bean.HelloService;
 6 
 7 public class BigKingTest {
 8     public static void main(String[] args) {
 9         System.out.println("开始初始化容器");
10         ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
11         System.out.println("初始化容器结束");
12         HelloService helloService = (HelloService) applicationContext.getBean("helloService");
13         HelloService helloService1 = (HelloService) applicationContext.getBean("helloService");
14         helloService.sayHello();
15         helloService1.sayHello();
16         System.out.println(helloService == helloService1);
17     }
18 }

 

application.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"
4        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
5     <bean class="top.bigking.bean.HelloService" id="helloService" scope="singleton" />
6 </beans>

控制台的输出如下:

 1  2 开始初始化容器
 3 DEBUG [main] - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3b95a09c
 4 DEBUG [main] - Loaded 1 bean definitions from class path resource [application.xml]
 5 DEBUG [main] - Creating shared instance of singleton bean 'helloService'
 6 初始化容器结束
 7 Hello, World
 8 Hello, World
 9 true
10 
11 Process finished with exit code 0

可以看到,在初始化容器时,helloService的bean对象实例就已经被创建了,后面的两次getBean都无法创建新的实例,而是直接使用这个实例,所以返回了true

以上,即可证明饿汉模式:启动容器时(即实例化容器时),为所有spring配置文件中定义的bean都生成一个实例,每次getBean请求获得的都是此实例

接下来我们证明懒汉模式:

修改application.xml,添加default-lazy-init属性

1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans default-lazy-init="true" xmlns="http://www.springframework.org/schema/beans"
3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
5     <bean class="top.bigking.bean.HelloService" id="helloService" scope="singleton" />
6 </beans>

运行结果如下:

 1  2 开始初始化容器
 3 DEBUG [main] - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3b95a09c
 4 DEBUG [main] - Loaded 1 bean definitions from class path resource [application.xml]
 5 初始化容器结束
 6 DEBUG [main] - Creating shared instance of singleton bean 'helloService'
 7 Hello, World
 8 Hello, World
 9 true
10 
11 Process finished with exit code 0

很明显可以看到,在容器初始化结束后,helloService实例才随着getBean被创建了出来

这样就证明了懒汉模式:在第一个请求时才生成一个实例,以后的请求都调用这个实例

 

问题来了,有了单例模式,那么一定有多例模式

多例模式:任何一个实例都是新的实例,调用getBean时,就new一个新实例

应该注意的是:多例模式中,实例只会随着getBean而创建,不会随着容器初始化而创建!也就是说,多例模式只有懒汉!

默认情况下scope="singleton",那么该Bean是单例

scope="prototype",则为多例,任何一个实例都是新的实例;

1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans default-lazy-init="true" xmlns="http://www.springframework.org/schema/beans"
3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
5     <bean class="top.bigking.bean.HelloService" id="helloService" scope="prototype" />
6 </beans>

运行看一下结果:

 1  2 开始初始化容器
 3 DEBUG [main] - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3b95a09c
 4 DEBUG [main] - Loaded 1 bean definitions from class path resource [application.xml]
 5 初始化容器结束
 6 Hello, World
 7 Hello, World
 8 false
 9 
10 Process finished with exit code 0

可以看到,最后的false

也就是说,这是两个被实例化的对象,是不同的!

有人可能会问,为什么控制台中,没有打印出 对象被实例化的相关信息呢?

这是因为:多例模式的对象,不归IOC容器管理!

posted @ 2019-12-15 14:20  ABKing  阅读(4472)  评论(0编辑  收藏  举报