javascript
【Spring】Bean的生命周期
Spring Bean是Spring應(yīng)用中最最重要的部分了。所以來(lái)看看Spring容器在初始化一個(gè)bean的時(shí)候會(huì)做那些事情,順序是怎樣的,在容器關(guān)閉的時(shí)候,又會(huì)做哪些事情。
示例代碼
git地址:
giraffe0813
giraffeInSpring
giraffeInSpring?, up-to-date spring版本:4.2.3.RELEASE
鑒于Spring源碼是用gradle構(gòu)建的,我也決定舍棄我大maven,嘗試下洪菊推薦過(guò)的gradle。運(yùn)行beanLifeCycle模塊下的junit test即可在控制臺(tái)看到如下輸出,可以清楚了解Spring容器在創(chuàng)建,初始化和銷毀Bean的時(shí)候依次做了那些事情。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | Spring容器初始化 ===================================== 調(diào)用GiraffeService無(wú)參構(gòu)造函數(shù) GiraffeService中利用set方法設(shè)置屬性值 調(diào)用setBeanName:: Bean Name defined in context=giraffeService 調(diào)用setBeanClassLoader,ClassLoader Name = sun.misc.Launcher$AppClassLoader 調(diào)用setBeanFactory,setBeanFactory:: giraffe bean singleton=true 調(diào)用setEnvironment 調(diào)用setResourceLoader:: Resource File Name=spring-beans.xml 調(diào)用setApplicationEventPublisher 調(diào)用setApplicationContext:: Bean Definition Names=[giraffeService, org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0, com.giraffe.spring.service.GiraffeServicePostProcessor#0] 執(zhí)行BeanPostProcessor的postProcessBeforeInitialization方法,beanName=giraffeService 調(diào)用PostConstruct注解標(biāo)注的方法 執(zhí)行InitializingBean接口的afterPropertiesSet方法 執(zhí)行配置的init-method 執(zhí)行BeanPostProcessor的postProcessAfterInitialization方法,beanName=giraffeService Spring容器初始化完畢 ===================================== 從容器中獲取Bean giraffe Name=李光洙 ===================================== 調(diào)用preDestroy注解標(biāo)注的方法 執(zhí)行DisposableBean接口的destroy方法 執(zhí)行配置的destroy-method Spring容器關(guān)閉 |
參考文檔
life cycle management of a spring bean
Spring Bean Life Cycle
Spring Bean的生命周期
先來(lái)看看,Spring在Bean從創(chuàng)建到銷毀的生命周期中可能做得事情。
initialization 和 destroy
有時(shí)我們需要在Bean屬性值set好之后和Bean銷毀之前做一些事情,比如檢查Bean中某個(gè)屬性是否被正常的設(shè)置好值了。Spring框架提供了多種方法讓我們可以在Spring Bean的生命周期中執(zhí)行initialization和pre-destroy方法。
1.實(shí)現(xiàn)InitializingBean和DisposableBean接口
這兩個(gè)接口都只包含一個(gè)方法。通過(guò)實(shí)現(xiàn)InitializingBean接口的afterPropertiesSet()方法可以在Bean屬性值設(shè)置好之后做一些操作,實(shí)現(xiàn)DisposableBean接口的destroy()方法可以在銷毀Bean之前做一些操作。
如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 | publicclass GiraffeService implementsInitializingBean,DisposableBean { ????@Override ????publicvoid afterPropertiesSet() throwsException { ????????System.out.println("執(zhí)行InitializingBean接口的afterPropertiesSet方法"); ????} ????@Override ????publicvoid destroy() throwsException { ????????System.out.println("執(zhí)行DisposableBean接口的destroy方法"); ????} } |
這種方法比較簡(jiǎn)單,但是不建議使用。因?yàn)檫@樣會(huì)將Bean的實(shí)現(xiàn)和Spring框架耦合在一起。
2.在bean的配置文件中指定init-method和destroy-method方法
Spring允許我們創(chuàng)建自己的init方法和destroy方法,只要在Bean的配置文件中指定init-method和destroy-method的值就可以在Bean初始化時(shí)和銷毀之前執(zhí)行一些操作。
如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 | publicclass GiraffeService { ????//通過(guò)<bean>的destroy-method屬性指定的銷毀方法 ????publicvoid destroyMethod() throwsException { ????????System.out.println("執(zhí)行配置的destroy-method"); ????} ????//通過(guò)<bean>的init-method屬性指定的初始化方法 ????publicvoid initMethod() throwsException { ????????System.out.println("執(zhí)行配置的init-method"); ????} } |
配置文件中的配置:
| 1 2 | <beanname="giraffeService"class="com.giraffe.spring.service.GiraffeService"init-method="initMethod"destroy-method="destroyMethod"> </bean> |
需要注意的是自定義的init-method和post-method方法可以拋異常但是不能有參數(shù)。
這種方式比較推薦,因?yàn)榭梢宰约簞?chuàng)建方法,無(wú)需將Bean的實(shí)現(xiàn)直接依賴于spring的框架。
3.使用@PostConstruct和@PreDestroy注解
除了xml配置的方式,Spring也支持用@PostConstruct和?@PreDestroy注解來(lái)指定init和destroy方法。這兩個(gè)注解均在javax.annotation包中。
為了注解可以生效,需要在配置文件中定義org.springframework.context.annotation.CommonAnnotationBeanPostProcessor或context:annotation-config
如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 | publicclass GiraffeService { ????@PostConstruct ????publicvoid initPostConstruct(){ ????????System.out.println("執(zhí)行PostConstruct注解標(biāo)注的方法"); ????} ????@PreDestroy ????publicvoid preDestroy(){ ????????System.out.println("執(zhí)行preDestroy注解標(biāo)注的方法"); ????} } |
配置文件:
| 1 | <beanclass="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/> |
實(shí)現(xiàn)*Aware接口 在Bean中使用Spring框架的一些對(duì)象
有些時(shí)候我們需要在Bean的初始化中使用Spring框架自身的一些對(duì)象來(lái)執(zhí)行一些操作,比如獲取ServletContext的一些參數(shù),獲取ApplicaitionContext中的BeanDefinition的名字,獲取Bean在容器中的名字等等。為了讓Bean可以獲取到框架自身的一些對(duì)象,Spring提供了一組名為*Aware的接口。
這些接口均繼承于org.springframework.beans.factory.Aware標(biāo)記接口,并提供一個(gè)將由Bean實(shí)現(xiàn)的set*方法,Spring通過(guò)基于setter的依賴注入方式使相應(yīng)的對(duì)象可以被Bean使用。
網(wǎng)上說(shuō),這些接口是利用觀察者模式實(shí)現(xiàn)的,類似于servlet listeners,目前還不明白,不過(guò)這也不在本文的討論范圍內(nèi)。
介紹一些重要的Aware接口:
- ApplicationContextAware: 獲得ApplicationContext對(duì)象,可以用來(lái)獲取所有Bean definition的名字。
- BeanFactoryAware:獲得BeanFactory對(duì)象,可以用來(lái)檢測(cè)Bean的作用域。
- BeanNameAware:獲得Bean在配置文件中定義的名字。
- ResourceLoaderAware:獲得ResourceLoader對(duì)象,可以獲得classpath中某個(gè)文件。
- ServletContextAware:在一個(gè)MVC應(yīng)用中可以獲取ServletContext對(duì)象,可以讀取context中的參數(shù)。
- ServletConfigAware在一個(gè)MVC應(yīng)用中可以獲取ServletConfig對(duì)象,可以讀取config中的參數(shù)。
如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | publicclass GiraffeService implements??ApplicationContextAware, ????????ApplicationEventPublisherAware, BeanClassLoaderAware, BeanFactoryAware, ????????BeanNameAware, EnvironmentAware, ImportAware, ResourceLoaderAware{ ?????????@Override ????publicvoid setBeanClassLoader(ClassLoader classLoader) { ????????System.out.println("執(zhí)行setBeanClassLoader,ClassLoader Name = " + classLoader.getClass().getName()); ????} ????@Override ????publicvoid setBeanFactory(BeanFactory beanFactory) throwsBeansException { ????????System.out.println("執(zhí)行setBeanFactory,setBeanFactory:: giraffe bean singleton=" +? beanFactory.isSingleton("giraffeService")); ????} ????@Override ????publicvoid setBeanName(String s) { ????????System.out.println("執(zhí)行setBeanName:: Bean Name defined in context=" ????????????????+ s); ????} ????@Override ????publicvoid setApplicationContext(ApplicationContext applicationContext) throwsBeansException { ????????System.out.println("執(zhí)行setApplicationContext:: Bean Definition Names=" ????????????????+ Arrays.toString(applicationContext.getBeanDefinitionNames())); ????} ????@Override ????publicvoid setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { ????????System.out.println("執(zhí)行setApplicationEventPublisher"); ????} ????@Override ????publicvoid setEnvironment(Environment environment) { ????????System.out.println("執(zhí)行setEnvironment"); ????} ????@Override ????publicvoid setResourceLoader(ResourceLoader resourceLoader) { ????????Resource resource = resourceLoader.getResource("classpath:spring-beans.xml"); ????????System.out.println("執(zhí)行setResourceLoader:: Resource File Name=" ????????????????+ resource.getFilename()); ????} ????@Override ????publicvoid setImportMetadata(AnnotationMetadata annotationMetadata) { ????????System.out.println("執(zhí)行setImportMetadata"); ????} } |
BeanPostProcessor
上面的*Aware接口是針對(duì)某個(gè)實(shí)現(xiàn)這些接口的Bean定制初始化的過(guò)程,
Spring同樣可以針對(duì)容器中的所有Bean,或者某些Bean定制初始化過(guò)程,只需提供一個(gè)實(shí)現(xiàn)BeanPostProcessor接口的類即可。 該接口中包含兩個(gè)方法,postProcessBeforeInitialization和postProcessAfterInitialization。 postProcessBeforeInitialization方法會(huì)在容器中的Bean初始化之前執(zhí)行, postProcessAfterInitialization方法在容器中的Bean初始化之后執(zhí)行。
如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | publicclass CustomerBeanPostProcessor implementsBeanPostProcessor { ????@Override ????publicObject postProcessBeforeInitialization(Object bean, String beanName) throwsBeansException { ????????System.out.println("執(zhí)行BeanPostProcessor的postProcessBeforeInitialization方法,beanName="+ beanName); ????????returnbean; ????} ????@Override ????publicObject postProcessAfterInitialization(Object bean, String beanName) throwsBeansException { ????????System.out.println("執(zhí)行BeanPostProcessor的postProcessAfterInitialization方法,beanName="+ beanName); ????????returnbean; ????} } |
要將BeanPostProcessor的Bean像其他Bean一樣定義在配置文件中
| 1 | <beanclass="com.giraffe.spring.service.CustomerBeanPostProcessor"/> |
總結(jié)
所以。。。結(jié)合第一節(jié)控制臺(tái)輸出的內(nèi)容,Spring Bean的生命周期是這樣紙的:
- Bean容器找到配置文件中Spring Bean的定義。
- Bean容器利用Java Reflection API創(chuàng)建一個(gè)Bean的實(shí)例。
- 如果涉及到一些屬性值 利用set方法設(shè)置一些屬性值。
- 如果Bean實(shí)現(xiàn)了BeanNameAware接口,調(diào)用setBeanName()方法,傳入Bean的名字。
- 如果Bean實(shí)現(xiàn)了BeanClassLoaderAware接口,調(diào)用setBeanClassLoader()方法,傳入ClassLoader對(duì)象的實(shí)例。
- 如果Bean實(shí)現(xiàn)了BeanFactoryAware接口,調(diào)用setBeanClassLoader()方法,傳入ClassLoader對(duì)象的實(shí)例。
- 與上面的類似,如果實(shí)現(xiàn)了其他*Aware接口,就調(diào)用相應(yīng)的方法。
- 如果有和加載這個(gè)Bean的Spring容器相關(guān)的BeanPostProcessor對(duì)象,執(zhí)行postProcessBeforeInitialization()方法
- 如果Bean實(shí)現(xiàn)了InitializingBean接口,執(zhí)行afterPropertiesSet()方法。
- 如果Bean在配置文件中的定義包含init-method屬性,執(zhí)行指定的方法。
- 如果有和加載這個(gè)Bean的Spring容器相關(guān)的BeanPostProcessor對(duì)象,執(zhí)行postProcessAfterInitialization()方法
- 當(dāng)要銷毀Bean的時(shí)候,如果Bean實(shí)現(xiàn)了DisposableBean接口,執(zhí)行destroy()方法。
- 當(dāng)要銷毀Bean的時(shí)候,如果Bean在配置文件中的定義包含destroy-method屬性,執(zhí)行指定的方法。
用圖表示一下(圖來(lái)源):
Spring BeanLifeCycle
原文出處:?Giraffe
from:?http://www.importnew.com/22350.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的【Spring】Bean的生命周期的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 高性能的关键:Spring MVC的异步
- 下一篇: Spring高级应用之注入各类集合