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容器管理!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM