1. 程式人生 > >bean的生命週期——Spring對bean的管理(三)

bean的生命週期——Spring對bean的管理(三)

本章案例基於上節,看不懂的請先看上節——bean的作用域:
https://blog.csdn.net/qq_34598667/article/details/83269250


bean的生命週期

1、bean的例項化:bean在何時被例項化?
2、bean的初始化:init-method:指定初始化回撥方法,在例項化 bean 時,立即呼叫該方法
3、bean的銷燬:destroy-method:銷燬回撥方法,只有從容器中移除 bean 之後,才能呼叫該方法。
4、預設的初始化和銷燬方法
beans標籤內部 default-init-method=“init” default-destroy-method=“destroy”


bean在何時被例項化?

大家已經學過servlet的生命週期了,servlet是被web容器進行管理的,而servlet的例項化有兩種方式:web容器在載入時和servlet被訪問時。與servlet類似,bean是被spring容器所管理的,所以bean的例項化無外乎兩種情況:
1、Spring容器啟動時。
2、呼叫getBean()方法時。
這裡我們要注意的是,bean的例項化時間跟Bean的作用域也有一定的關係,我們以上節內容spring bean的作用域為基礎舉例

1)當bean的作用域為singleton時

修改Demo類,新增構造方法:

public class
Demo { public Demo(){ System.out.println("正在例項化..."); } private String name; }

然後修改spring.xml的配置檔案如下,使用scope的預設值:

<?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.xsd">
<!-- 構造器例項化 --> <bean id="demo" class="com.oak.junit.day01.Demo"></bean> </beans>

即bean的作用域為singleton時,我們修改測試類的程式碼,新增測試方法為:

	@Test
	public void testLife(){
		//例項化Spring容器
		ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); 
	}

控制檯輸出:
正在例項化...
說明了當bean的作用域為singleton時,bean物件是在Spring容器啟動時就進行建立了。即預設情況下會在容器啟動時初始化bean。
我們也可以指定bean的初始化時機為在呼叫getBean()方法時被初始化,使用bean元素的lazy-init屬性:
lazy-init:true,延遲初始化的 bean 告訴 Ioc 容器在它第一次被請求時,而不是在啟動時去建立一個 bean 例項。
修改bean節點程式碼為:

	<!-- 構造器例項化 -->
	<bean id="demo" class="com.oak.junit.day01.Demo" scope="prototype"
	lazy-init="true"></bean>

直接測試發現並沒有任何輸出,更改測試方法為:

	@Test
	public void testLife(){
		//例項化Spring容器
		ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); 
		Demo demo=ctx.getBean("demo",Demo.class);
	}

重新測試發現控制檯輸出:
正在例項化...
則說明了lazy-init=”true”指定了不要在Spring容器啟動時對這個bean進行例項化。

如果想對所有bean都應用延遲初始化,可以在根節點beans設定default-lazy-init=“true”,程式碼如下:

<?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.xsd" 
        default-lazy-init="true">

    ......

</beans>


2)當bean的作用域為prototype時

修改spring.xml配置檔案,刪除bean節點的lazy-init=”true”,程式碼如下:

	<!-- 構造器例項化 -->
	<bean id="demo" class="com.oak.junit.day01.Demo" scope="prototype"></bean>

增加測試方法如下:

	@Test
	public void testLifePrototype(){
		//例項化Spring容器
		ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); 
	}

進行測試發現沒有任何輸出,修改測試方法,增加getBean()方法的呼叫

	@Test
	public void testLifePrototype(){
		//例項化Spring容器
		ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); 
		Demo demo=ctx.getBean("demo",Demo.class);
	}

控制檯輸出:
正在例項化...
說明當bean的作用域為prototype時,bean物件並不會在Spring容器啟動時就進行建立。 bean物件將會在呼叫getBean()方法時進行建立。


bean的初始化

我們希望在bean被初始化的時候,就初始化某些資源。為了達到這樣的目的,我們可以給類新增初始化方法:

public class Demo {
	//定義初始化方法
	public void init(){
		System.out.println("正在被初始化...");
	}
	public Demo(){
		System.out.println("正在例項化...");
	}
	private String name;
}

在Spring.xml中為bean指定初始化方法,使用bean元素的init-method屬性:

     <!-- 構造器例項化 -->
	<bean id="demo" class="com.oak.junit.day01.Demo" lazy-init="false" init-method="init"></bean>

執行測試方法:

	@Test
	public void testInit(){
		//例項化Spring容器
		ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); 
	}

控制檯輸出:

正在例項化...
正在初始化...

bean的銷燬

現在我們又希望在bean被銷燬的時候,就釋放或關閉某些資源。為了達到這樣的目的,我們可以給類新增指定的銷燬方法:

public class Demo {
	//初始化方法
	public void init(){
		System.out.println("正在初始化...");
	}
	public Demo(){
		System.out.println("正在例項化...");
	}
	//銷燬方法
    public void destroy() {
        System.out.println("釋放初始化的資源");
    }
	private String name;	
}

在Spring.xml中為bean指定初始化方法,使用bean元素的init-method屬性:

     <!-- 構造器例項化 -->
	<bean id="demo" class="com.oak.junit.day01.Demo" lazy-init="false" init-method="init" 	destroy-method="destroy"></bean>

新增測試方法並執行:

	@Test
	public void testDestory(){
		//例項化Spring容器
		AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); 
		//正常關閉Spring容器
		ctx.close();
	}

控制檯輸出:

正在例項化...
正在初始化...
釋放初始化的資源

PS:bean銷燬的時機

bean到底是什麼時候銷燬的呢?如果沒有人為地刪除它,預設該bean一直在Spring容器中, 也就是說隨著Spring容器的關閉,該bean才會被銷燬。

預設的初始化和銷燬方法

在beans標籤內部新增 default-init-method=“init” default-destroy-method=“destroy”
修改spring.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.xsd"
        default-init-method="init" 
        default-destroy-method="destroy">
	       <!-- 構造器例項化 -->
	<bean id="demo" class="com.oak.junit.day01.Demo" lazy-init="false"></bean>
</beans>

新增測試方法:

	@Test
	public void testLife(){
		//例項化Spring容器
		AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); 
		ctx.close();
	}

控制檯輸出:

正在例項化...
正在初始化...
釋放初始化的資源

下一章:IOC