日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > 互聯網 > Spring核心技術IoC容器(六)

Spring核心技術IoC容器(六)

來源:程序員人生   發布時間:2016-06-24 13:27:47 閱讀次數:2464次

前文已描寫了Bean的作用域,本文將描寫Bean的1些生命周期作用,配置還有Bean的繼承。

定制Bean

生命周期回調

開發者通過實現Spring的InitializeingBeanDisposableBean接口,就能夠讓容器來管理Bean的生命周期。容器會調用afterPropertiesSet()前和destroy()后才會允許Bean在初始化和燒毀Bean的時候履行1些操作。

JSR⑵50的@PostConstruct@PreDestroy注解就是現代Spring利用生命周期回調的最好實踐。使用這些注解意味著Bean不在耦合在Spring特定的接口上。詳細內容,后續將會介紹。
如果開發者不想使用JSR⑵50的注解,依然可以斟酌使用init-methoddestroy-method定義來解耦。

內部來講,Spring框架使用BeanPostProcessor的實現來處理任何接口的回調,BeanPostProcessor能夠找到并調用適合的方法。如果開發者需要1些Spring其實不直接提供的生命周期行動,開發者可以自行實現1個BeanPostProcessor。更多的信息可以參考后面的容器擴大點。

除初始化和燒毀回調,Spring管理的對象也實現了Lifecycle接口來讓管理的對象在容器的生命周期內啟動和關閉。

生命周期回調在本節會進行詳細描寫。

初始化回調

org.springframework.beans.factory.InitializingBean接口允許Bean在所有的必要的依賴配置配置完成后來履行初始化Bean的操作。InitializingBean接口中特指了1個方法:

void afterPropertiesSet() throws Exception;

Spring團隊建議開發者不要使用InitializingBean接口,由于這樣會沒必要要的將代碼耦合到Spring之上。而通過使用@PostConstruct注解或指定1個POJO的實現方法,比實現接口要更好。在基于XML的配置元數據上,開發者可使用init-method屬性來指定1個沒有參數的方法。使用Java配置的開發者可使用@Bean當中的initMethod屬性,比如以下:

<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
public class ExampleBean { public void init() { // do some initialization work } }

與以下代碼1樣效果:

<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
public class AnotherExampleBean implements InitializingBean { public void afterPropertiesSet() { // do some initialization work } }

但是前1個版本的代碼是沒有耦合到Spring的。

燒毀回調

實現了org.springframework.beans.factory.DisposableBean接口的Bean就可以通讓容器通過回調來燒毀Bean所用的資源。DisposableBean接口包括了1個方法:

void destroy() throws Exception;

同InitializingBean一樣,Spring團隊依然不建議開發者來使用DisposableBean回調接口,由于這樣會將開發者的代碼耦合到Spring代碼上。換種方式,比如使用@PreDestroy注解或指定1個Bean支持的配置方法,比如在基于XML的配置元數據中,開發者可以在Bean標簽上指定destroy-method屬性。而在Java配置中,開發者可以配置@BeandestroyMethod

<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
public class ExampleBean { public void cleanup() { // do some destruction work (like releasing pooled connections) } }

上面的代碼配置和以下配置是同等的:

<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
public class AnotherExampleBean implements DisposableBean { public void destroy() { // do some destruction work (like releasing pooled connections) } }

但是第1段代碼是沒有耦合到Spring的。

<bean/>標簽的destroy-method可以被配置為特殊指定的值,來方便讓Spring能夠自動的檢查到closeshutdown方法(可以實現java.lang.AutoCloseablejava.io.Closeable都會匹配。)這個特殊指定的值可以配置到<beans/>default-destroy-method來讓所有的Bean實現這個行動。

默許初始化和燒毀方法

當開發者不使用Spring獨有的InitializingBeanDisposableBean回調接口來實現初始化和燒毀方法的時候,開發者通常定義的方法名字都是好似init()initialize()或是dispose()等等。那末,想這類的方法就能夠標準化,來讓所有的開發者都使用1樣的名字來確保1致性。

開發者可以配置Spring容器來針對每個Bean都查找這類名字的初始化和燒毀回調函數。也就是說,任何的1個利用開發者,都會在利用的類中使用1個叫init()的初始化回調,而不需要在每一個Bean中定義init-method="init"這中屬性。Spring IoC容器會在Bean創建的時候調用那個方法(就如前面描寫的標準生命周期1樣。)這個特性也強迫開發者為其他的初始化和燒毀回調函數使用一樣的名字。

假定開發者的初始化回調方法名字為init()而燒毀的回調方法為destroy()。那末開發者的類就會好似以下的代碼:

public class DefaultBlogService implements BlogService { private BlogDao blogDao; public void setBlogDao(BlogDao blogDao) { this.blogDao = blogDao; } // this is (unsurprisingly) the initialization callback method 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容器辨認叫做init的方法來作為Bean的初始化回調方法。當Bean創建和裝載以后,如果Bean有這么1個方法的話,Spring容器就會在適合的時候調用。

類似的,開發者也能夠配置默許燒毀回調函數,基于XML的配置就在<beans/>標簽上面使用default-destroy-method屬性。

當存在1些Bean的類有了1些回調函數,而和配置的默許回調函數不同的時候,開發者可以通過特指的方式來覆蓋掉默許的回調函數。以XML為例,就是通過使用<bean>標簽的init-methoddestroy-method來覆蓋掉<beans/>中的配置。

Spring容器會做出以下保證,Bean會在裝載了所有的依賴以后,立刻就開始履行初始化回調。這樣的話,初始化回調只會在直接的Bean援用裝載好后調用,而AOP攔截器還沒有利用到Bean上。首先目標Bean會完全初始化好,然后,AOP代理和其攔截鏈才能利用。如果目標Bean和代理是分開定義的,那末開發者的代碼乃至可以跳過AOP而直接和援用的Bean交互。因此,在初始化方法中利用攔截器會前后矛盾,由于這樣做耦合了目標Bean的生命周期和代理/攔截器,還會由于同Bean直接交互而產生奇怪的現象。

聯合生命周期機制

在Spring 2.5以后,開發者有3種選擇來控制Bean的生命周期行動:

  • InitializingBeanDisposableBean回調接口
  • 自定義的init()destroy方法
  • 使用@PostConstruct@PreDestroy注解

開發者也能夠在Bean上聯合這些機制1起使用

如果Bean配置了多個生命周期機制,而且每一個機制配置了不同的方法名字,那末每一個配置的方法會依照后面描寫的順序來履行。但是,如果配置了相同的名字,比如說初始化回調為init(),在不止1個生命周期機制配置為這個方法的情況下,這個方法只會履行1次。

如果1個Bean配置了多個生命周期機制,并且含有不同的方法名,履行的順序以下:

  • 包括@PostConstruct注解的方法
  • InitializingBean接口中的afterPropertiesSet()方法
  • 自定義的init()方法

燒毀方法的履行順序和初始化的履行順序相同:

  • 包括@PreDestroy注解的方法
  • DisposableBean接口中的destroy()方法
  • 自定義的destroy()方法

啟動和關閉回調

Lifecycle接口中為任何有自己生命周期需求的對象定義了基本的方法(比如啟動和停止1些后臺進程):

public interface Lifecycle { void start(); void stop(); boolean isRunning(); }

任何Spring管理的對象都可實現上面的接口。那末當ApplicationContext本身遭到了啟動或停止的信號時,ApplicationContext會通過拜托LifecycleProcessor來串連上下文中的Lifecycle的實現。

public interface LifecycleProcessor extends Lifecycle { void onRefresh(); void onClose(); }

從上面代碼我們可以發現LifecycleProcessorLifecycle接口的擴大。LifecycleProcessor增加了另外的兩個方法來針對上下文的刷新和關閉做出反應。

常規的org.springframework.context.Lifecycle接口只是為明確的開始/停止通知提供1個契約,而其實不表示在上下文刷新時自動開始。斟酌實現org.springframework.context.SmartLifecycle接口可以取代在某個Bean的自動啟動進程(包括啟動階段)中的細粒度控制。同時,停止通知其實不能保證在燒毀之前出現:在正常的關閉情況下,所有的LifecycleBean都會在燒毀回調準備好之前收到停止停止,但是,在上下文存活期的熱刷新或停止刷新嘗試的時候,只會調用燒毀方法。

啟動和關閉調用是很重要的。如果不同的Bean之間存在depends-on的關系的話,被依賴的1方需要更早的啟動,而且關閉的更早。但是,有的時候直接的依賴是未知的,而開發者僅僅知道哪種類型需要更早進行初始化。在這類情況下,SmartLifecycle接口定義了另外一種選項,就是其父接口Phased中的getPhase()方法。

public interface Phased { int getPhase(); }
public interface SmartLifecycle extends Lifecycle, Phased { boolean isAutoStartup(); void stop(Runnable callback); }

當啟動時,具有最低的phased的對象優先啟動,而當關閉時,是相反的順序。因此,如果1個對象實現了SmartLifecycle然后令其getPhase()方法返回了Integer.MIN_VALUE的話,就會讓該對象最早啟動,而最晚燒毀。明顯,如果getPhase()方法返回了Integer.MAX_VALUE就說明了該對象會最晚啟動,而最早燒毀。當斟酌到使用phased的值得時候,也同時需要了解正常沒有實現SmartLifecycleLifecycle對象的默許值,這個值為0。因此,任何負值將標兵對象會在標準組件啟動之前啟動,在標準組件燒毀以后再進行燒毀。

SmartLifecycle接口也定義了1個stop的回調函數。任何實現了SmartLifecycle接口的函數都必須在關閉流程完成以后調用回調中的run()方法。這樣做可以是能異步關閉。而LifecycleProcessor的默許實現DefaultLifecycleProcessor會等到配置的超時時間以后再調用回調。默許的每階段的超時時間為30秒。開發者可以通過定義1個叫做lifecycleProcessor的Bean來覆蓋默許的生命周期處理器。如果開發者需要配置超時時間,可以通過以下代碼:

<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor"> <!-- timeout value in milliseconds --> <property name="timeoutPerShutdownPhase" value="10000"/> </bean>

和前文提到的,LifecycleProcessor接口定義了回調方法來刷新和關閉山下文。關閉的話,如果stop()方法已明確調用了,那末就會驅動關閉的流程,但是如果是上下文關閉就不會產生這類情況。而刷新的回調會使能SmartLifecycle的另外一個特性。當上下文刷新終了(所有的對象已實例化并初始化),那末就會調用回調,默許的生命周期處理器會檢查每個SmartLifecycle對象的isAutoStartup()返回的Bool值。如果為真,對象將會自動啟動而不是等待明確的上下文調用,或調用自己的start()方法(不同于上下文刷新,標準的上下文實現是不會自動啟動的)。phased的值和depends-on關系會決定對象啟動和燒毀的順序。

在非Web利用關閉Spring IoC容器

這1部份只是針對非Web的利用。Spring的基于web的ApplicationContext實現已有代碼在web利用關閉的時候能夠優雅的關閉Spring IoC容器。

如果開發者在非web利用環境使用Spring IoC容器的話, 比如,在桌面客戶真個環境下,開發者需要在JVM上注冊1個關閉的鉤子。來確保在關閉Spring IoC容器的時候能夠調用相干的燒毀方法來釋放掉對應的資源。固然,開發者也必須要正確的配置和實現那些燒毀回調。

開發者可以在ConfigurableApplicationContext接口調用registerShutdownHook()來注冊燒毀的鉤子:

import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public final class Boot { public static void main(final String[] args) throws Exception { ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext( new String []{"beans.xml"}); // add a shutdown hook for the above context... ctx.registerShutdownHook(); // app runs here... // main method exits, hook is called prior to the app shutting down... } }

ApplicationContextAwareBeanNameAware

ApplicationContext在創建實現了org.springframework.context.ApplicationContextAware接口的對象時,該對象的實例會包括1個到ApplicationContext的援用。

public interface ApplicationContextAware { void setApplicationContext(ApplicationContext applicationContext) throws BeansException; }

這樣Bean就可以夠通過編程的方式操作和創建ApplicationContext了。通過ApplicationContext接口,或通過將援用轉換成已知的接口的子類,比如ConfigurableApplicationContext就可以夠顯式1些額外的功能。其中的1個用法就是可以通過編程的方式來獲得其他的Bean。有的時候這個能力很有用,但是,Spring團隊推薦最好避免這樣做,由于這樣會耦合代碼到Spring上,同時也沒有遵守IoC的風格。其他的ApplicationContext的方法可以提供1些到資源的訪問,發布利用事件,或進入MessageSource。這些信息在后續的針對ApplicationContext的描寫中會講到。

在Spring 2.5版本,自動裝載也是取得ApplicationContext的1種方式。傳統的構造函數和通過類型的裝載方式(前文Spring核心技術IoC容器(4)有相干描寫)可以通過構造函數或是setter方法的方式注入。開發者也能夠通過注解注入的方式使用更多的特性。

ApplicationContext創建了1個實現了org.springframework.beans.factory.BeanNameAware接口的類,那末這個類就能夠針對其名字進行配置。

public interface BeanNameAware { void setBeanName(string name) throws BeansException; }

這個回調的調用途于屬性配置完以后,但是初始化回調之前,比如InitializingBeanafterPropertiesSet()方法和自定義的初始化方法等。

其他Aware接口

除上面描寫的兩種Aware接口,Spring還提供了1系列的Aware接口來讓Bean告知容器,這些Bean需要1些具體的基礎設施信息。最重要的1些Aware接口都在下面表中進行了描寫:

名字 注入的依賴
ApplicationContextAware 聲明的ApplicationContext
ApplicationEventPlulisherAware ApplicationContext中的事件發布器
BeanClassLoaderAware 加載Bean使用的類加載器
BeanFactoryAware 聲明的BeanFactory
BeanNameAware Bean的名字
BootstrapContextAware 容器運行的資源適配器BootstrapContext,通常僅在JCA環境下有效
LoadTimeWeaverAware 加載期間處理類定義的weaver
MessageSourceAware 解析消息的配置策略
NotificationPublisherAware Spring JMX通知發布器
PortletConfigAware 容器當前運行的PortletConfig,僅在web下的Spring ApplicationContext中可見
PortletContextAware 容器當前運行的PortletContext,僅在web下的Spring ApplicationContext中可見
ResourceLoaderAware 配置的資源加載器
ServletConfigAware 容器當前運行的ServletConfig,僅在web下的Spring ApplicationContext中可見
ServletContextAware 容器當前運行的ServletContext,僅在web下的Spring ApplicationContext中可見

再次的聲明,上面這些接口的使用時違背IoC原則的,除非必要,最好不要使用。

Bean繼承

Bean的定義可以包括很多的配置信息,包括構造參數,屬性等等,也能夠包括1些容器指定的信息,比如初始化方法,工廠方法等等。子Bean會繼承父Bean的配置信息。子Bean也能夠覆蓋父Bean的1些值,或增加1些值。通過定義父Bean和子Bean可以減少配置內容,是1種高效的模板性能。

如果開發者通過編程的方式跟ApplicationContext交換,就會知道子Bean是通過ChildBeanDefinition類表示的。大多數的開發者不需要再這個級別上來跟子Bean定義交互,只需要在ClassPathXmlApplicationContext中顯式的配置Bean就能夠了。當使用基于XML的元數據配置的時候,開發者通過使用parent屬性來定義子Bean,以下所示:

<bean id="inheritedTestBean" abstract="true" class="org.springframework.beans.TestBean"> <property name="name" value="parent"/> <property name="age" value="1"/> </bean> <bean id="inheritsWithDifferentClass" class="org.springframework.beans.DerivedTestBean" parent="inheritedTestBean" init-method="initialize"> <property name="name" value="override"/> <!-- the age property value of 1 will be inherited from parent --> </bean>

如上述代碼所示,子Bean如果沒有配置任何內容,是直接使用父Bean的配置信息的,固然了,如果配置了,將會覆蓋父Bean的配置。

子Bean會繼承父Bean的作用范圍,構造參數值,屬性值,和覆蓋父Bean的方法,可以增加新的值。任何的作用域,初始化方法,燒毀方法,或靜態工廠方法配置,開發者都可以覆蓋父Bean的配置。

有1些配置都是從子Bean定義中讀取的:depends-on,自動裝載模式,依賴檢查,單例,延遲初始化。

前面的例子通過使用abstract標簽來使父Bean抽象,如果父定義沒有指定類,那末久需要使用屬性abstract以下:

<bean id="inheritedTestBeanWithoutClass" abstract="true"> <property name="name" value="parent"/> <property name="age" value="1"/> </bean> <bean id="inheritsWithClass" class="org.springframework.beans.DerivedTestBean" parent="inheritedTestBeanWithoutClass" init-method="initialize"> <property name="name" value="override"/> <!-- age will inherit the value of 1 from the parent bean definition--> </bean>

父Bean是沒法被實例化的,由于它是不完全的,會被標志位abstract。當使用abstract的時候,其配置就作為純模板來使用了。如果嘗試在abctract的父Bean中援用了其他的Bean或調用getBean()都會返回毛病。容器內部的preInstantiateSingletons()方法會疏忽掉那些定義為抽象的Bean。

ApplicationContext會默許預初始化所有的單例。因此,如果開發者配置了1個父Bean作為模板,而且其定義了指定的類,那末開發者就必須配置抽象屬性為true,否則,利用上下文會嘗試預初始化這個父Bean。

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 国产爱视频| 成人精品国产免费网站 | 国产麻豆 | 一区二区三区视频 | 欧美一区二 | 国产精品久久久一区 | 欧美成人视屏 | 久久精品视频在线 | 精品久久久久久久人人人人传媒 | 一级黄色av| 亚洲国产精品麻豆 | 久久久精品视频国产 | 日韩麻豆 | 欧美成人一区二区三区片免费 | www.com黄 | 国产一区二区三区视频观看 | 精品一区电影 | av黄色网 | 精品一区二区免费视频 | 国产精品最新 | 91中文视频 | 久久精彩| 国产精品久久久久久久9999 | 久久精品一区二区三区不卡牛牛 | 91伦理电影 | 欧美日韩中文字幕在线视频 | 国产免费专区 | 狠狠干网站| 中文字幕成人网 | 日韩三级久久 | 一区二区三区色 | 91视频一区二区三区 | 亚洲国产91| 亚洲精品高清视频 | 香蕉av777xxx色综合一区 | av片在线看免费高清网站 | 免费视频爱爱太爽了 | www.精品久久| 国产成人毛片 | 亚洲免费视频观看 | 久久久国产精品 |