您好,登錄后才能下訂單哦!
如何在spring中回調bean的生命周期?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
生命周期回調方法
對于spring bean來講,我們默認可以指定兩個生命周期回調方法。一個是在ApplicationContext將bean初始化,包括注入對應的依賴后的回調方法;另一個是在ApplicationContext準備銷毀之前的回調方法。要實現這種回調主要有三種方式:實現特定的接口、在XML配置文件中指定回調方法和使用JSR-250標準的注解。
1 實現特定接口
針對bean初始化后的回調和ApplicationContext銷毀前的回調,Spring分別為我們了提供了InitializingBean和DisposableBean接口供用戶實現,這樣Spring在需要進行回調時就會調用對應接口提供的回調方法。
1.1 InitializingBean
InitializingBean是用來定義ApplicationContext在完全初始化一個bean以后需要需要回調的方法的,其中只定義了一個afterPropertiesSet()方法。如其名稱所描述的那樣,該方法將在ApplicationContext將一個bean完全初始化,包括將對應的依賴項都注入以后才會被調用。InitializingBean的完全定義如下。
public interface InitializingBean { void afterPropertiesSet() throws Exception; }
由于InitializingBean的afterPropertiesSet()方法會在依賴項都進行注入以后再回調,所以該方法通常會用來檢查必要的依賴注入,以使我們能夠在bean被初始化時就發現其中的錯誤,而不是在很長時間使用以后才發現。如果你去看Spring的源碼,你就會發現源碼中有很多InitializingBean的使用,而且基本都是用來檢查必要的依賴項是否為空的。
public class Hello implements InitializingBean { private World world; /** * 該方法將在當前bean被完全初始化后被調用 */ public void afterPropertiesSet() throws Exception { Assert.notNull(world, "world should not be null."); } public void setWorld(World world) { this.world = world; } }
9.1.2 DisposableBean
DisposableBean是用來定義在ApplicationContext銷毀之前需要回調的方法的。DisposableBean接口中只定義了一個destroy()方法,在ApplicationContext被銷毀前,Spring將依次調用bean容器中實現了DisposableBean接口的destroy()方法。所以,我們可以通過實現該接口的destroy()方法來達到在ApplicationContext銷毀前釋放某些特定資源的目的。
public interface DisposableBean { void destroy() throws Exception; }
在Spring的源碼中,也有很多實現了DisposableBean接口的類,如我們熟悉的ApplicationContext實現類、SingleConnectionDataSource等。
2 在XML中配置回調方法
在XML配置文件中通過bean元素定義一個bean時,我們可以通過bean元素的init-method屬性和destroy-method屬性來指定當前bean在初始化以后和ApplicationContext銷毀前的回調方法。需要注意的是所指定的回調方法必須是沒有參數的。
通過init-method屬性來指定初始化方法時所對應的方法必須是該bean中所擁有的方法,所以首先我們需要在對應的bean中定義對應的初始化方法,這里假設我們需要在bean中定義一個init()方法作為該bean的初始化方法,那么我們可以對我們的bean進行類似如下定義。
public class Hello { private World world; /** * 該方法將被用來作為初始化方法,在當前bean被完全初始化后被調用 */ public void init() { Assert.notNull(world, "world should not be null."); } public void setWorld(World world) { this.world = world; } }
接下來就是在XML配置文件中定義該bean時通過init-method屬性定義對應的初始化方法為init()方法,init-method屬性的屬性值就對應初始化方法的名稱,所以我們的bean應該是如下定義。
<bean name="world" class="com.app.World"/> <!-- 通過init-method屬性指定初始化方法名稱 --> <bean id="hello" class="com.app.Hello" init-method="init"> <property name="world" ref="world"/> </bean>
init-method和destroy-method的用法和配置等基本上都是一樣的,所以對于使用destroy-method來指定ApplicationContext銷毀前的回調方法的用法就不再贅述了。
如果我們的初始化方法或銷毀方法的名稱大都是一樣的,在通過init-method和destroy-method進行指定的時候我們就沒有必要一個個bean都去指定了,Spring允許我們在最頂級的beans元素上指定默認的初始化后回調方法和銷毀前的回調方法名稱,這樣對于沒有指定init-method或destroy-method的bean將默認將其中default-init-method或default-destroy-method屬性值對應名稱的方法(如果存在的話)視為初始化后的回調方法或銷毀前的回調方法。這是通過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.xsd" default-init-method="init" default-destroy-method="destroy"> </beans>
以上表示定義默認的初始化后回調方法名稱為init,默認的銷毀前回調方法名稱為destroy。
當定義了default-init-method或default-destroy-method以后,如果我們的某個bean對應的初始化后回調方法名稱或銷毀前的回調方法名稱與默認定義的不一樣,則我們可以在對應的bean上通過init-method或destroy-method指定該bean自身的回調方法名稱,即bean上定義的回調方法名稱將會比默認定義擁有更高的優先級。
3 使用JSR-250標準的注解
關于bean的生命周期回調方法,Spring也會JSR-250標準注解做了支持,即在bean完全初始化后將回調使用@PostConstruct標注的方法,在銷毀ApplicationContext前將回調使用@PreDestroy標注的方法。
針對之前的示例,如果我們現在把定義的bean定義成如下這樣,即沒有在bean上通過init-method和destroy-method指定初始化方法和銷毀方法。
<bean name="world" class="com.app.World"/> <bean id="hello" class="com.app.Hello"> <property name="world" ref="world"/> </bean>
當然,這里也不考慮全局性的init-method和destroy-method方法,如果我們希望在id為“hello”的bean被初始化后回調其中的init()方法,在銷毀前回調其中的destroy()方法,我們就可以通過@PostConstruct和@PreDestroy進行如下定義。
public class Hello { private World world; /** * 該方法將被用來作為初始化方法,在當前bean被完全初始化后被調用 */ @PostConstruct public void init() { Assert.notNull(world, "world should not be null."); } @PreDestroy public void destroy() { System.out.println("---------destroy-----------"); } public void setWorld(World world) { this.world = world; } }
使用JSR-250標準指定初始化后的回調方法以及銷毀前的回調方法時,如果我們希望將多個方法都作為對應的回調方法進行回調,則可以在多個方法上同時使用對應的注解進行標注,Spring將依次執行對應的方法。
public class Hello { private World world; @PostConstruct public void init() { System.out.println("-----------init-------------"); } /** * 該方法將被用來作為初始化方法,在當前bean被完全初始化后被調用 */ @PostConstruct public void init2() { Assert.notNull(world, "world should not be null."); } @PreDestroy public void destroy() { System.out.println("------------destroy----------------"); } @PreDestroy public void destroy2() { System.out.println("---------destroy2-----------"); } public void setWorld(World world) { this.world = world; } }
4 混合使用三種方式
Spring允許我們混合使用上述介紹的三種方式來指定對應的回調方法。當對于同一個bean使用三種方式指定了同一個方法作為初始化后的回調方法或銷毀前的回調方法,則對應的回調方法只會被執行一次。然而,當對于同一個bean使用兩種或三種方式指定的回調方法不是同一個方法時,Spring將依次執行使用不同的方式指定的回調方法。對于初始化后的回調方法而言,具體規則如下:
使用@PostConstruct標注的方法。
實現InitializingBean接口后的回調方法afterPropertiesSet()方法。
通過init-method或default-init-method指定的方法。
對于銷毀前的回調方法而言,其規則是一樣的:
使用@PreDestroy標注的方法。
實現DisposableBean接口后的回調方法destroy()方法。
通過destroy-method或default-destroy-method指定的方法。
關于如何在spring中回調bean的生命周期問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。