1. 程式人生 > >spring中的DisposableBean和InitializingBean

spring中的DisposableBean和InitializingBean

在spring容器初始化bean和銷燬bean的以前的操作有很多種,目前我知道的有:在xml中定義的時候用init-methoddestory-method

還可以使用beans的default-init-method和default-destroy-method屬性來設定所有bean的預設的初始化和銷燬方法。(這種情況下如果bean有對應的方法則會執行對應的初始化和銷燬方法)。
定義一個Demon類:

package com.moonlit.myspring;

public class Demon {
    public void defaultBorn() {
        System.out.println("the demon was born.");
    }
    public void doAction() {
        System.out.println("the demon do destroys");
    }
    public void defaultDead() {
        System.out.println("the demon is dead.");
    }
}

配置其Bean:
<bean id="demon" class="com.moonlit.myspring.Demon" />

我們配置beans的default-init-method和default-destroy-method屬性如下:

<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.0.xsd"
    default-init-method="defaultBorn"
    default-destroy-method="defaultDead" >


可以使用bean的init-method和destroy-method屬性來初始化和銷燬bean。
定義一個Hero類:
package com.moonlit.myspring;

public class Hero {
    public void born() {
        System.out.println("the hero is born.");
    }
    public void defaultBorn() {
        System.out.println("the hero is born by default.");
    }
    public void doAction() {
        System.out.println("the hero save the world.");
    }
    public void dead() {
        System.out.println("the hero is dead.");
    }
    public void defaultDead() {
        System.out.println("the hero was dead by default.");
    }
}

配置其bean:
 <bean id="hero" class="com.moonlit.myspring.Hero"
           init-method="born"
           destroy-method="dead" />
測試
package com.moonlit.practice;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.moonlit.myspring.Demon;
import com.moonlit.myspring.Hero;

public class PracticeHero {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "spring-idol.xml");
        Hero hero = (Hero) context.getBean("hero");
        hero.doAction();
        Demon demon = (Demon) context.getBean("demon");
        demon.doAction();
    }
}

輸出結果如下:
the hero is born.
the demon was born.
the hero save the world.
the demon do destroys

不能看到銷燬的效果,可能是因為程式結束的時候物件還沒有執行銷燬的方法。(暫時還不知道怎麼檢測destroy-method),但是可以看到init-method的方法。因為Hero的bean定義了init-method和destroy-method,所以程式會先找born()和dead()兩個方法執行;但是Demon的bean沒有定義init-method方法和destroy-method方法,所以程式會執行beans裡面定義的default-init-method和default-destroy-method方法執行,所以輸出的效果是這樣的。

理解:使用bean元素的init-method和destroy-method元素可以定義一個bean在初始化和銷燬時使用的方法;也可以通過beans的default-init-method和default-destroy-method元素來指定所有bean的預設初始化和銷燬的方法。

還有一種就是定義bean的時候實現DisposableBean和InitializingBean 這兩個介面,

package com.moonlit.myspring;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Spiderman implements InitializingBean, DisposableBean {
    public void destroy() throws Exception {
        System.out.println("the spider man is dead...He will be back.");
    }
    public void doAction() {
        System.out.println("spider man saved Gotham City");
    }
    public void afterPropertiesSet() throws Exception {
        System.out.println("The Dark Knight Rises");
    }
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "spring-idol.xml");
        Spiderman spiderman = (Spiderman) context.getBean("spiderman");
        spiderman.doAction();
    }
}

輸出效果如下:
the hero is born.
the demon was born.
The Dark Knight Rises
spider man saved Gotham City

開啟InitializingBean 的原始碼


public interface InitializingBean {

    /**
     * Invoked by a BeanFactory after it has set all bean properties supplied
     * (and satisfied BeanFactoryAware and applicationContextAware).
     * <p>This method allows the bean instance to perform initialization only
     * possible when all bean properties have been set and to throw an
     * exception in the event of misconfiguration.
     * @throws Exception in the event of misconfiguration (such
     * as failure to set an essential property) or if initialization fails.
     */
    void afterPropertiesSet() throws Exception;

}

根據註解很清楚的可以看出,afterPropertiesSet()表示在資源載入完以後,初始化bean之前執行的方法,我猜想spring底層應該會在初始化bean的時候,應該會使用(bean instanceof InitializingBean)判斷是不是實現了這個介面,其實在很多框架中都是這麼幹的,但是因為沒研究過spring原始碼,暫且還不知道底層原理。這樣我們就可以在初始化的時候,做一些自己想要做的事了。

同理,DisposableBean就是在一個bean被銷燬的時候,spring容器會幫你自動執行這個方法,估計底層原理也是差不多的,對於一些使用完之後需要釋放資源的bean,我們都會實現這個介面,或者是配置destory-method方法。原始碼也基本是相似的,只是把afterPropertiesSet改為destroy。