<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## 4.6 自定義 bean 的性質 ### 4.6.1 生命周期回調 為了和容器管理 bean 的生命周期進行交互,你可以實現 Spring 的 InitializingBean 和 DisposableBean 接口。容器為前者調用 afterPropertiesSet()方法,為后者調 用 destroy()方法在 bean 的初始化和銷毀階段允許 bean 執行特定的動作。你也可以和容 器達到相同的整合,而不需要通過使用初始化方法和銷毀方法的對象定義元數據來耦合你的類到 Spring 的接口中。 從內部來說,Spring Framework 使用了 BeanPostProcessor 的實現來處理任何回調 接口,它可以發現并調用合適的方法。如果你需要自定義特性或其它生命周期行為,Spring 不會提供開箱,你可以自行實現 BeanPostProcessor 接口。要獲取更多信息,可以參考 4.8 節,“容器擴展點”。 除了初始化和銷毀回調,Spring 管理的對象也會實現 Lifecycle 接口,所以那些對象 可以參與到啟動和關閉過程,來作為容器自己的生命周期。 生命周期回調接口在本節中來說明。 #### 4.6.1.1 初始化回調 org.springframework.beans.factory.InitializingBean 接口允許 bean 在 所有必須的屬性被容器設置完成之后來執行初始化工作。InitializingBean 接口中僅僅 指定了一個方法: ``` void afterPropertiesSet() throws Exception; ``` 推薦不要使用 InitializingBean 接口,因為它不必要地將代碼耦合到 Spring 中。 另外,可以指定一個 POJO 初始化方法。在基于 XML 配置元數據的情形中,你可以使用 init-method 屬性來指定簽名為無返回值,無參數的方法的名稱。比如,下面的定義: ``` <bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/> public class ExampleBean { public void init() { // 做一些初始化工作 } } ``` 這和下面的做法是完全相同的: ``` <bean id="exampleInitBean" class="examples.AnotherExampleBean"/> public class AnotherExampleBean implements InitializingBean { public void afterPropertiesSet() { //做一些初始化工作 } } ``` 但是沒有耦合任何代碼到 Spring 中。 #### 4.6.1.2 銷毀回調 實現 org.springframework.beans.factory.DisposableBean 接口,當容器 包含的 bean 被銷毀時,允許它獲得回調。DisposableBean 接口中僅僅有一個方法: ``` void destroy() throws Exception; ``` 推薦不要使用 DisposableBean 接口,因為它不必要地將代碼耦合到 Spring 中。另外, 可以指定一個由 bean 支持的通用的方法。使用基于 XML 配置元數據,你可以使用`<bean/>` 元素中的 destroy-method 屬性。比如,下面的定義: ``` <bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/> public class ExampleBean { public void cleanup() { // 做一些銷毀工作 (比如釋放連接池的連接) } } ``` 這和下面的做法是完全相同的: ``` <bean id="exampleInitBean" class="examples.AnotherExampleBean"/> public class AnotherExampleBean implements DisposableBean { public void destroy() { // 做一些銷毀工作 (比如釋放連接池的連接) } } ``` 但是沒有耦合代碼到 Spring 中。 #### 4.6.1.3 默認的初始化和銷毀方法 當使用 Spring 指定的 InitializingBean 和 DisposableBean 回調接口來編寫初 始化和銷毀方法回調時,典型地做法就是編寫名稱為 init(),initialize(),dispose() 等方法.理想的情況,這樣的生命周期回調方法的名稱在一個項目中是標準化的,那么所有 的開發人員可以使用相同的方法名稱來保證一致性。 你可以配置 Spring 容器在每個 bean 中來查看命名的初始化和銷毀回調方法名稱。這就 是說,作為應用程序開發人員,你可以編寫應用類并且使用初始化回調方法 init(),而不 需要在每個 bean 的定義中來配置 init-method="init"屬性。當 bean 被創建時(并按 照前面描述的標準的生命周期回調合約),Spring 的 IoC 容器調用這個方法。這個特性也對 初始化和銷毀方法回調強制執行了一致的命名約定。 假設你的初始化回調方法命名為 init(),銷毀回調方法命名為 destroy()。那么你 就可以按照如下示例來裝配類: ``` public class DefaultBlogService implements BlogService { private BlogDao blogDao; public void setBlogDao(BlogDao blogDao) { this.blogDao = blogDao; } // 這是(毋庸置疑的)初始化回調方法 public void init() { if (this.blogDao == null) { throw new IllegalStateException("The [blogDao] property must be set."); } } } <beans default-init-method="init"> <bean id="blogService" class="com.foo.DefaultBlogService"> <property name="blogDao" ref="blogDao" /> </bean> </beans> ``` 頂層`<beans/>`元素的 default-init-method 屬性的存在,就會讓 Spring 的 IoC 容 器意識到在 bean 中的一個叫做 init 的方法就是初始化回調方法。當一個 bean 被創建和裝 配時,如果 bean 類有這樣一個方法,那么它就會在合適的時間被調用。 相似地(也就是在 XML 中 ), 你 可 以 使 用 頂 層 元 素 `<beans/>` 的 default-destroy-method 屬性來配置銷毀回調方法。 在已經存在的 bean 類中,有命名差異的回調方法,你可以指定(也就是在 XML 中) `<bean/>`本身的 init-method 和 destroy-method 屬性來覆蓋默認的方法。 Spring 容器保證了在給 bean 提供所有的依賴后,配置的初始化回調方法會立即被調用。 因此初始化回調也被稱為原始的 bean 引用,也就意味著 AOP 的攔截器等尚未應用到 bean 中。目標 bean 首先被完全創建,之后 AOP 代理(比方說)和它的攔截器鏈就會被應用上。 如果目標 bean 和代理分開來定義了,你的代碼仍然可以繞開代理和原始目標 bea n 來交互。 因此,引用攔截器到初始化方法中會是不一致的,因為這么來做了會和它的代理/攔截耦合 目標 bean 的合生命周期,當你的代碼直接和原始目標 bean 交互時,會留下奇怪的語義。 #### 4.6.1.4 組合生命周期機制 在 Spring 2.5 中,對控制 bean 的生命周期行為有三種選擇:InitializingBean(4.6.1.1節)和 DisposableBean(4.6.1.2 節)回調接口;自定義 init()和 destroy()方法; @PostConstruct 和@PreDestroy 注解(4.9.6 節)。你可以組合這些機制來控制給定的 bean。 > ![](img/note.gif) > 注意 > 如果對一個 bean 配置了多個生命周期機制,并且每種機制都用不同的方法名稱來配置, 那么每個配置方法就會以下面列出的順序來執行。然而,如果配置了相同的方法名稱,比如說,init()對于初始化方法,多于一個生命周期機制,那么這個方法就執行一次,這在前 面章節解釋過了。 相同的 bean 配置了不同初始化方法的多個生命周期機制,那么就按下面順序調用: * 使用@PostConstruct 注解的方法 * 由 InitializingBean 回調接口定義的 afterPropertiesSet()方法 自定義配置的 init()方法 銷毀方法也是同樣順序調用: * 使用@PreDestroy 注解的方法 * 由 DisposableBean 回調接口定義的 destroy ()方法 * 自定義配置的 destroy ()方法 #### 4.6.1.5 啟動和關閉回調 Lifecycle 接口定義了對于任意有它自己生命周期需求(比如,開始和結束一些后臺 進程)對象的必要方法: ``` public interface Lifecycle { void start(); void stop(); boolean isRunning(); } ``` 任何 Spring 管理的對象可以實現這個接口。那么,當 ApplicationContext 本身啟動和關 閉時,它會級聯那些定義在上下文中,對所有生命周期實現的調用。它會委托給 LifecycleProcessor 來做: ``` public interface LifecycleProcessor extends Lifecycle { void onRefresh(); void onClose(); } ``` 要注意 LifecycleProcessor 本身是擴展了 Lifecycle 接口。而且它添加了兩個 方法來對上下文的刷新和關閉做出反應。 啟動和關閉調用的順序是很重要的。如果一個“依賴”關系存在于兩個任意對象間,那 么需要依賴的一方會在它的依賴啟動之后啟動,并且在它的依賴關閉之前停止。然而,有時 直接的依賴關系是未知的。你可能僅僅知道確定類型的對象應該優先于另外一種類型對象的啟動。在那些情形下,SmartLifecycle 接口定義了另外一種選擇,命名為 getPhase() 方法,在它的父接口 Phased 中來定義。 ``` public interface Phased { int getPhase(); } public interface SmartLifecycle extends Lifecycle, Phased { boolean isAutoStartup(); void stop(Runnable callback); } ``` 當 啟 動 時 , 最 低 層 的 對 象 首 先 啟 動 , 當 停 止 時 , 是 相 反 的 。 因 此 , 實 現 了 SmartLifecycle 接口,并且 getPhase()方法返回 Integer.MIN_VALUE 的對象就會在最 先開始和最后停止的中間。在范圍的另外一端,Integer.MIN_VALUE 的層次值表示對象 應該最后啟動并且最先停止(可能是因為它取決于其它進程的執行)。當考慮層次值時,知道任意“普通”對象并且沒有實現 Lifecycle 接口的默認的層次是 0,這也是很重要的。 因此,任意負的層次值就表示對象應該在那些標準組件之前啟動(在它們之后停止),對于 任意正的層次值,反之亦然。 正如你看到由 SmartLifecycle 定義的停止方法接收回調。任何實現類必須在實現類關閉進程完成之后,調用回調方法 run()。這使得必要時可以進行異步關閉,因為默認的 LifecycleProcessor 接口的實現,DefaultLifecycleProcessor,,會等待每個階 段一組對象來調用回調的超時值。每個階段的默認超時是 30 秒。你可以在上下文中定義名 為“lifecycleProcessor”的 bean 來覆蓋默認的生命周期進程實例。如果你僅僅想去修改超時 時間,那么定義下面的 bean 就足夠了: ``` <bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProc essor"> <!-- 毫秒數的超時時間 --> <property name="timeoutPerShutdownPhase" value="10000"/> </bean> ``` 正如所提到的,LifecycleProcessor 接口定義了刷新和關閉上下文的回調方法。后 者將驅動關閉進程,就好像明確地調用了 stop()方法,但是當上下文關閉時它才會發生。另 一方面,‘刷新’回調使得 SmartLifecycle bean 的另外一個特性可用。當上下文刷新時(在所有對象都被實例化和初始化后),才會調用回調方法,在那時,默認的生命周期進程 會檢查每個 SmartLifecycle 對象的 isAutoStartup()方法返回的布爾值。如果是“true”,那時對象將會被啟動,而不是等待明確的上下文調用或它自己的 start()方法(不像上下文刷新,對標準的上下文實現來說,上下文啟動不會自動發生)。“階段”值和任意“依 賴”關系會按照上面所描述的相同方式來決定啟動的順序。 #### 4.6.1.6 在非 Web 應用中,優雅地關閉 Spring IoC 容器 > ![](img/note.gif) > 注意 > 本節僅對非 Web 應用來說。在相關 Web 應用程序關閉時,Spring 的基于 Web 的 ApplicationContext 實現已經有代碼來優雅地關閉 Spring 的 Ioc 容器了。 如果你在非 Web 應用環境中使用 Spring 的 IoC 容器;比如,在富客戶端桌面環境中; 你在 JVM 中注冊了一個關閉的鉤子。這么來做就保證了優雅地關閉并且在單例 bean 中調用相關銷毀方法,那么所有資源都會被釋放。當然,你必須正確配置并實現這些銷毀回調方法。 要注冊 一個 關閉 鉤子, 可以 調用 AbstractApplicationContext 類中 聲明的registerShutdownHook()方法: ``` import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationConte xt; public final class Boot { public static void main(final String[] args) throws Exception { AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(new String []{"beans.xml"}); // 對上面的上下文添加一個關閉的鉤子... ctx.registerShutdownHook(); // 這里運行應用程序... // 主方法退出,鉤子在應用關閉前優先被調用... } } ``` ### 4.6.2 ApplicationContextAware 和 BeanNameAware 當 ApplicationContext 創 建 實 現 了 org.springframework.context.ApplicationContextAware 接口的類時,這個類 就被提供了一個 ApplicationContext 的引用。 ``` public interface ApplicationContextAware { void setApplicationContext(ApplicationContext applicationContext) throws BeansException; } ``` 因此 bean 就可以編程來操作創建 它們的 ApplicationContext ,通過 ApplicationContext 接口,或者轉換到這個接口的已知子 類型,比如 ConfigurableApplicationContext,會公開更多的功能。一種使用方式就是編程式獲 取其它的 bean。有時候這種能力是很有用的。然而,通常你應該避免這么來做,因為它會耦合代碼到 Spring 中,還沒有協作者作為屬性提供給 bean 的控制反轉的風格。應用上下文 的其它方法提供了訪問文件資源,公共應用事件和訪問消息資源的方法。這些補充特性為在 4.14 節,“應用上下文的補充功能”來說明。 在 Spring 2.5 中,自動裝配是獲取 ApplicationContext 引用的另外一種方式。“傳 統的”constructor 和 byType 自動裝配模式(在 4.4.5 節,“自動裝配協作者”中說明的) 可以分別為構造方法參數或 setter 方法參數提供 ApplicationContext 類型的依賴。為了更大的靈活性,包括自動裝配字段和多參數方法的能力,還有使用新的基于注解的自動裝 配特性。如果字段,構造方法或者普通方法進行@Autowired 注解,而且你這么做了, ApplicationFactory 就會自動裝配到期望 BeanFactory 類型的字段,構造方法參數或方法參數。要獲取更多信息,可以參考 4.9.2 節,“@Autowired 和@Inject”。 當 應 用 上 下 文 創 建 實 現 了 org.springframework.beans.factory.BeanNameAware 接口的類時,這個類會被 提供一個在相關對象中定義的命名引用。 ``` public interface BeanNameAware { void setBeanName(string name) throws BeansException; } ``` 回 調 函 數 在 普 通 bean 的 屬 性 被 填 充 之 后 并 且 在 如 InitializingBean 的 afterPropertiesSet 或自定義初始化方法的初始化回調之前被調用。 ### 4.6.3 其它 Aware 接口 除了上面討論的 ApplicationContextAware 和 BeanNameAware,Spring 還提供了很多 Aware 接口,它們允許 bean 來告訴容器它們需要確定的基礎的依賴。最重要的 Aware 接口在下面總結出來了-作為一個通用的規則,名稱就很好地說明了依賴的類型: 表 4.4 Aware 接口 | 名稱 | 注入的依賴 | 何處解釋 | | --- | --- | --- | | ApplicationContextA ware | 聲明 ApplicationContext | 4.6.2 節,“ ApplicationContextAware 和 BeanNameAware” | | ApplicationEventPub lisherAware | 包含在 ApplicationContext內的事件發布 | 4.14 節,“應用上下文的補充 功能” | | BeanClassLoaderAware | 用于加載 bean 類的類加載器 | 4.3.2 節,“實例化 bean” | | BeanFactoryAware | 聲明 BeanFactory | 4.6.2 節,“ ApplicationContextA ware 和 BeanNameAware” | | BeanNameAware | 聲明 bean 的名稱 | 4.6.2 節,“ ApplicationContextA ware 和 BeanNameAware”| | BootstrapContextAwa re | 容器運行的資源適配器 BootstrapContext。典型地 是 僅 僅 在 JCA 感 知 的 ApplicationContext 中可 用。| 第 24 章,JCA CCI | | LoadTimeWeaverAware | 在加載時為處理類定義的織入 器 | 8.8.4 節,“Spring Framework中使用 Aspect J 進行加載時織 入”| | MessageSourceAware | 解析消息配置的策略(支持參數化和國際化)| 4.14 節,“應用上下文的補充功能”| | NotificationPublisherAware| Spring JMX 通知發布 | 23.7 節,“通知” | | PortletConfigAware | 容 器 運 行 的 當 前 的PortletConfig。僅在感知 Web 的 Spring 的 ApplicationContext 中有 效| 第 19 章,Portlet MVC 框架 | | PortletContextAware | 容 器 運 行 的 當 前 的PortletContext。僅在感知 Web 的 Spring 的 ApplicationContext 中有 效| 第 19 章,Portlet MVC 框架 | | ResourceLoaderAware | 為低級別的資源訪問配置的加載器| 第 5 章,資源 | | ServletConfigAware | 容 器 運 行 的 當 前 的ServletConfig。僅在感知 Web 的 Spring 的ApplicationContext 中有效| 第 16 章,Web MVC 框架 | | ServletContextAware | 容 器 運 行 的 當 前 的ServletContext。僅在感知 Web 的 Spring 的 ApplicationContext 中有 效| 第 16 章,Web MVC 框架 | 請再次注意綁定你的代碼到 Spring API 的這些接口的使用,并不再遵循控制反轉風格。 因此,它們被推薦使用到基礎的 bean 中,那些 bean 需要編程式地訪問容器。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看