Spring容器在默認情況下管理的bean是單例(singleton)的,即該bean只會創造一個對象,無論之后調用多少次該bean,都只會返回同一個對象。
多例(prototype)模式,每次調用同一個bean,都會創造不同的對象。
實驗:
兩個實驗類:
package com.tsvv.pojo; public class Apple { } --------------------------------------- package com.tsvv.pojo; public class Orange { }
application.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"> <!-- scope屬性控制當前bean的創建模式: singleton:單例模式中,默認為是此模式 prototype:多例模式 --> <bean id="apple" class="com.tsvv.pojo.Apple" scope="singleton"></bean> <bean id="orange" class="com.tsvv.pojo.Orange" scope="prototype"></bean> </beans>
Test:
package com.tsvv.ioc; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.tsvv.pojo.Apple; import com.tsvv.pojo.Orange; public class TestDemo { ApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); @Test public void testScope() { Apple apple1=(Apple)context.getBean("apple"); Apple apple2=(Apple)context.getBean("apple"); Apple apple3=(Apple)context.getBean("apple"); Orange orange1=(Orange)context.getBean("orange"); Orange orange2=(Orange)context.getBean("orange"); Orange orange3=(Orange)context.getBean("orange"); System.out.println("apple1----->"+apple1); System.out.println("apple2----->"+apple2); System.out.println("apple3----->"+apple3); System.out.println("orange1----->"+orange1); System.out.println("orange2----->"+orange2); System.out.println("orange3----->"+orange3); } }
結果:
apple1----->com.tsvv.pojo.Apple@4386f16 apple2----->com.tsvv.pojo.Apple@4386f16 apple3----->com.tsvv.pojo.Apple@4386f16 orange1----->com.tsvv.pojo.Orange@363ee3a2 orange2----->com.tsvv.pojo.Orange@4690b489 orange3----->com.tsvv.pojo.Orange@79b06cab
區別與聯系:
單例模式和多例模式屬於對象模式,但是單例模式的對象在整個系統中只有一份,多例模式可以有多個實例;它們都不對外提供構造方法,即構造方法都為私有。
之所以用單例,是因為沒必要每個請求都新建一個對象,這樣子既浪費CPU又浪費內存;
之所以用多例,是為了防止並發問題:即一個請求改變了對象的狀態,此時對象又處理另一個請求,而之前請求對對象狀態的改變導致了對象對另一個請求做了錯誤的處理;
用單例和多例的標准只有一個:當對象含有可改變的狀態時(更精確的說就是在實際應用中該狀態會改變),則多例,否則單例;
生命周期:
單例:
bean在單例模式下,IOC容器啟動時解析xml發現該bean標簽后,直接創建該bean的對象存入內部map中保存,此后無論調用多少次getBean()獲取該bean都是從map中獲取該對象返回,一直是一個對象。此對象一直被IOC容器持有,直到容器退出時,隨着容器的退出對象被銷毀。
多例:
bean在多例模式下,IOC容器啟動時解析xml發現該bean標簽后,只是將該bean進行管理,並不會創建對象,此后每次使用 getBean()獲取該bean時,IOC都會重新創建該對象返回,每次都是一個新的對象。這個對象IOC容器並不會持有,何時銷毀取決於使用該對象的用戶自己什么時候銷毀該對象。
