無依賴bean建立和銷燬的順序
我們先來看一下沒有任何依賴的bean的建立和銷燬的順序。
下面的xml中定義了3個bean:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="
xmlns:xsi="
xsi:schemaLocation="
/spring-beans-4.3.xsd">
<bean id="bean3" class="com.javacode2018.lesson001.demo7.NormalBean$Bean3"/>
<bean id="bean2" class="com.javacode2018.lesson001.demo7.NormalBean$Bean2"/>
<bean id="bean1" class="com.javacode2018.lesson001.demo7.NormalBean$Bean1"/></beans>12345678910
注意上面xml中bean定義順序是:bean3、bean2、bean1。
對應java程式碼如下:
package com.javacode2018.lesson001.demo7;import org.springframework.beans.factory.DisposableBean;/**
* 無任何依賴的bean建立的順序
*/public class NormalBean {
public static class Bean1 implements DisposableBean {
public Bean1() {
System.out.println(this.getClass() + " constructor!");
}
@Override
public void destroy() throws Exception {
System.out.println(this.getClass() + " destroy()");
}
}
public static class Bean2 implements DisposableBean {
public Bean2() {
System.out.println(this.getClass() + " constructor!");
}
@Override
public void destroy() throws Exception {
System.out.println(this.getClass() + " destroy()");
}
}
public static class Bean3 implements DisposableBean {
public Bean3() {
System.out.println(this.getClass() + " constructor!");
}
@Override
public void destroy() throws Exception {
System.out.println(this.getClass() + " destroy()");
}
}}1234567891011121314151617181920212223242526272829303132333435363738394041424344
上面程式碼中使用到了DisposableBean介面,這個是spring容器提供的一個介面,這個介面中有個destroy方法,我們的bean類可以實現這個介面,當我們呼叫容器的close方法關閉容器的時候,spring會呼叫容器中所有bean的destory方法,用來做一些清理的工作,這個以後還會細講的。
上面幾個類中構造方法和destory方法中都有輸出。
下面我們來搞個測試用例看一下spring容器啟動和關閉的過程中,定義的3個bean的建立和銷燬的順序。
package com.javacode2018.lesson001.demo7;import com.javacode2018.lesson001.demo5.IocUtils;import org.junit.Test;import org.springframework.context.support.ClassPathXmlApplicationContext;/**
* dependon詳解
*/public class DependOnTest {
/**
* 無依賴的bean建立和銷燬的順序
*/
@Test
public void normalBean() {
System.out.println("容器啟動中!");
String beanXml = "classpath:/com/javacode2018/lesson001/demo7/normalBean.xml";
ClassPathXmlApplicationContext context = IocUtils.context(beanXml);
System.out.println("容器啟動完畢,準備關閉spring容器!");
//關閉容器
context.close();
System.out.println("spring容器已關閉!");
}}1234567891011121314151617181920212223242526
執行上面的normalBean方法,輸出:
容器啟動中!class com.javacode2018.lesson001.demo7.NormalBean$Bean3 constructor!class com.javacode2018.lesson001.demo7.NormalBean$Bean2 constructor!class com.javacode2018.lesson001.demo7.NormalBean$Bean1 constructor!容器啟動完畢,準備關閉spring容器!class com.javacode2018.lesson001.demo7.NormalBean$Bean1 destroy()class com.javacode2018.lesson001.demo7.NormalBean$Bean2 destroy()class com.javacode2018.lesson001.demo7.NormalBean$Bean3 destroy()spring容器已關閉!123456789
bean的定義結合上面輸出我們來對比一下:
bean定義順序 |
建立順序 |
銷燬順序 |
bean3 |
bean3 |
bean1 |
bean2 |
bean2 |
bean2 |
bean1 |
bean1 |
bean3 |
從輸出中可以得到2點結論:
-
bean物件的建立順序和bean xml中定義的順序一致
-
bean銷燬的順序和bean xml中定義的順序相反
透過構造器強依賴bean建立和銷燬順序
我們將上面案例改造一下,透過建構函式注入的方式使bean之間產生強依賴。
package com.javacode2018.lesson001.demo7;import org.springframework.beans.factory.DisposableBean;/**
* 強依賴的bean建立和銷燬順序
*/public class StrongDependenceBean {
public static class Bean1 implements DisposableBean {
public Bean1() {
System.out.println(this.getClass() + " constructor!");
}
@Override
public void destroy() throws Exception {
System.out.println(this.getClass() + " destroy()");
}
}
public static class Bean2 implements DisposableBean {
private Bean1 bean1;
public Bean2(Bean1 bean1) { //@1
this.bean1 = bean1;
System.out.println(this.getClass() + " constructor!");
}
@Override
public void destroy() throws Exception {
System.out.println(this.getClass() + " destroy()");
}
}
public static class Bean3 implements DisposableBean {
private Bean2 bean2;
public Bean3(Bean2 bean2) { //@2
this.bean2 = bean2;
System.out.println(this.getClass() + " constructor!");
}
@Override
public void destroy() throws Exception {
System.out.println(this.getClass() + " destroy()");
}
}}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
程式碼解釋:
@1:建立Bean2的時候需要傳入一個bean1物件,對bean1產生了強依賴
@2:建立Bean3的時候需要傳入一個bean2物件,對bean2產生了強依賴
依賴關係是:
bean3->bean2->bean11
對應的配置(strongDependenceBean.xml):
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="
xmlns:xsi="
xsi:schemaLocation="
/spring-beans-4.3.xsd">
<bean id="bean3" class="com.javacode2018.lesson001.demo7.StrongDependenceBean$Bean3">
<constructor-arg index="0" ref="bean2"/> //@1
</bean>
<bean id="bean2" class="com.javacode2018.lesson001.demo7.StrongDependenceBean$Bean2">
<constructor-arg index="0" ref="bean1"/> //@2
</bean>
<bean id="bean1" class="com.javacode2018.lesson001.demo7.StrongDependenceBean$Bean1">
</bean></beans>123456789101112131415
注意上面xml中bean定義順序是:bean3、bean2、bean1。
@1:bean3中透過構造器注入bean2
@2:bean2中透過構造器注入bean1
DependOnTest中建立一個測試用例,如下:
/**
* 強依賴的bean的建立和銷燬順序測試
*/@Testpublic void strongDependenceBean() {
System.out.println("容器啟動中!");
String beanXml = "classpath:/com/javacode2018/lesson001/demo7/strongDependenceBean.xml";
ClassPathXmlApplicationContext context = IocUtils.context(beanXml);
System.out.println("容器啟動完畢,準備關閉spring容器!");
context.close();
System.out.println("spring容器已關閉!");}123456789101112
執行strongDependenceBean方法輸出:
容器啟動中!class com.javacode2018.lesson001.demo7.StrongDependenceBean$Bean1 constructor!class com.javacode2018.lesson001.demo7.StrongDependenceBean$Bean2 constructor!class com.javacode2018.lesson001.demo7.StrongDependenceBean$Bean3 constructor!容器啟動完畢,準備關閉spring容器!class com.javacode2018.lesson001.demo7.StrongDependenceBean$Bean3 destroy()class com.javacode2018.lesson001.demo7.StrongDependenceBean$Bean2 destroy()class com.javacode2018.lesson001.demo7.StrongDependenceBean$Bean1 destroy()spring容器已關閉!123456789
bean的定義結合上面輸出我們來對比一下:
bean定義順序 |
依賴順序(下面依賴上面的) |
建立順序 |
銷燬順序 |
bean3 |
bean1 |
bean1 |
bean3 |
bean2 |
bean2 |
bean2 |
bean2 |
bean1 |
bean3 |
bean3 |
bean1 |
從輸出中可以得到2點結論:
-
bean物件的建立順序和bean依賴的順序一致
-
bean銷燬的順序和bean建立的順序相反
透過depend-on干預bean建立和銷燬順序
上面看到了對於無依賴的bean,透過定義的順序確實可以干預bean的建立順序,透過強依賴也可以干預bean的建立順序。
那麼如果xml中定義的bean特別多,而有些bean之間也沒有強依賴關係,此時如果想去調整bean的建立和銷燬的順序,得去調整xml中bean的定義順序,或者去加強依賴,這樣是非常不好的,spring中可以透過depend-on來解決這些問題,在不調整bean的定義順序和強加依賴的情況下,可以透過透過depend-on屬性來設定當前bean的依賴於哪些bean,那麼可以保證depend-on指定的bean在當前bean之前先建立好,銷燬的時候在當前bean之後進行銷燬。
depend-on使用方式:
<bean id="bean1" class="" depend->
depend-on:設定當前bean依賴的bean名稱,可以指定多個,多個之間可以用”,;空格“進行分割
上面不管bean2,bean2,bean4在任何地方定義,都可以確保在bean1建立之前,會先將bean2,bean3,bean4建立好,表示bean1依賴於這3個bean,可能bean1需要用到bean2、bean3、bean4中生成的一些資源或者其他的功能等,但是又沒有強制去在bean1類中透過屬性定義強依賴的方式去依賴於bean2、bean3、bean4;當然銷燬的時候也會先銷燬當前bean,再去銷燬被依賴的bean,即先銷燬bean1,再去銷燬depend-on指定的bean。
下面我們來個案例看一下:
dependOnBean.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="
xmlns:xsi="
xsi:schemaLocation="
/spring-beans-4.3.xsd">
<bean id="bean3" class="com.javacode2018.lesson001.demo7.NormalBean$Bean3" depends-on="bean2,bean1"/>
<bean id="bean2" class="com.javacode2018.lesson001.demo7.NormalBean$Bean2"/>
<bean id="bean1" class="com.javacode2018.lesson001.demo7.NormalBean$Bean1"/></beans>12345678910
上面xml中先定義的bean3,然後定義了bean2和bean1,並且指定了bean3的depend->
上面xml對應的java程式碼如下:
shandong/
package com.javacode2018.lesson001.demo7;import org.springframework.beans.factory.DisposableBean;/**
* 透過depend-on來干預bean建立和銷燬順序
*/public class DependOnBean {
public static class Bean1 implements DisposableBean {
public Bean1() {
System.out.println(this.getClass() + " constructor!");
}
@Override
public void destroy() throws Exception {
System.out.println(this.getClass() + " destroy()");
}
}
public static class Bean2 implements DisposableBean {
public Bean2() {
System.out.println(this.getClass() + " constructor!");
}
@Override
public void destroy() throws Exception {
System.out.println(this.getClass() + " destroy()");
}
}
public static class Bean3 implements DisposableBean {
public Bean3() {
System.out.println(this.getClass() + " constructor!");
}
@Override
public void destroy() throws Exception {
System.out.println(this.getClass() + " destroy()");
}
}}1234567891011121314151617181920212223242526272829303132333435363738394041424344
DependOnTest中建立測試用例:
nanchang/
/**
* 透過depend-on來干預bean建立和銷燬順序
*/@Testpublic void dependOnBean() {
System.out.println("容器啟動中!");
String beanXml = "classpath:/com/javacode2018/lesson001/demo7/dependOnBean.xml";
ClassPathXmlApplicationContext context = IocUtils.context(beanXml);
System.out.println("容器啟動完畢,準備關閉spring容器!");
context.close();
System.out.println("spring容器已關閉!");}123456789101112
執行dependOnBean方法輸出:
lanzhou/
容器啟動中!class com.javacode2018.lesson001.demo7.NormalBean$Bean2 constructor!class com.javacode2018.lesson001.demo7.NormalBean$Bean1 constructor!class com.javacode2018.lesson001.demo7.NormalBean$Bean3 constructor!容器啟動完畢,準備關閉spring容器!class com.javacode2018.lesson001.demo7.NormalBean$Bean3 destroy()class com.javacode2018.lesson001.demo7.NormalBean$Bean1 destroy()class com.javacode2018.lesson001.demo7.NormalBean$Bean2 destroy()spring容器已關閉!123456789
總結
haerbin/
-
無依賴的bean建立順序和定義的順序一致,銷燬順序剛好相反
-
透過構造器強依賴的bean,會先建立構造器引數中對應的bean,然後才會建立當前bean,銷燬順序剛好相反
-
depend-on可以指定檔期bean依賴的bean,透過這個可以確保depend-on指定的bean在當前bean建立之前先建立好,銷燬順序剛好相反
-
bean的銷燬順序和bean建立的順序相反
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30239065/viewspace-2731316/,如需轉載,請註明出處,否則將追究法律責任。