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