您好,登錄后才能下訂單哦!
本篇文章為大家展示了怎么深入了解Spring的Bean生命周期,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。
對(duì)于普通的 Java 對(duì)象,當(dāng) new 的時(shí)候創(chuàng)建對(duì)象,然后該對(duì)象就能夠使用了。一旦該對(duì)象不再被使用,則由 Java 自動(dòng)進(jìn)行垃圾回收。
而 Spring 中的對(duì)象是 bean,bean 和普通的 Java 對(duì)象沒(méi)啥大的區(qū)別,只不過(guò) Spring 不再自己去 new 對(duì)象了,而是由 IoC 容器去幫助我們實(shí)例化對(duì)象并且管理它,我們需要哪個(gè)對(duì)象,去問(wèn) IoC 容器要即可。IoC 其實(shí)就是解決對(duì)象之間的耦合問(wèn)題,Spring Bean 的生命周期完全由容器控制。
Spring bean的生命周期階段是:
1.bean定義
:就是從xml或注解定位資源加載讀取bean的元信息并定義成一個(gè)BeanDefinition對(duì)象
2.bean注冊(cè)
:將BeanDefinition對(duì)象根據(jù)相應(yīng)的規(guī)則放到緩存池map中
3.實(shí)例化
:根據(jù)BeanDefinition實(shí)例化真正的bean,即是調(diào)用構(gòu)造函數(shù)
4.依賴(lài)注入
:屬性賦值調(diào)用setter方法,即是依賴(lài)注入(DI)
5.初始化
: 初始化是用戶(hù)能自定義擴(kuò)展的階段
6.銷(xiāo)毀
: 銷(xiāo)毀是用戶(hù)能自定義擴(kuò)展的階段
注:其他都是在這階段前后的擴(kuò)展點(diǎn)
refresh()
public void refresh() throws BeansException, IllegalStateException { synchronized(this.startupShutdownMonitor) { StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh"); // 準(zhǔn)備Bean初始化相關(guān)的環(huán)境信息,其內(nèi)部提供了一個(gè)空實(shí)現(xiàn)的initPropertySources()方法用于提供給用戶(hù)一個(gè)更改相關(guān)環(huán)境信息的機(jī)會(huì) this.prepareRefresh(); // 創(chuàng)建BeanFactory實(shí)例,并且注冊(cè)相關(guān)的bean信息 ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); // 注冊(cè)Aware和Processor實(shí)例,并且注冊(cè)了后續(xù)處理請(qǐng)求所需的一些Editor信息 this.prepareBeanFactory(beanFactory); try { // 提供的一個(gè)空方法,用于供給子類(lèi)對(duì)已經(jīng)生成的BeanFactory的一些信息進(jìn)行定制 this.postProcessBeanFactory(beanFactory); StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process"); // 調(diào)用BeanFactoryPostProcessor及其子接口的相關(guān)方法,這些接口提供了一個(gè)入口,提供給了調(diào)用方一個(gè)修改已經(jīng)生成的BeanDefinition的入口 this.invokeBeanFactoryPostProcessors(beanFactory); // 對(duì)BeanPostProcessor進(jìn)行注冊(cè) this.registerBeanPostProcessors(beanFactory); beanPostProcess.end(); // 初始化國(guó)際化所需的bean信息 this.initMessageSource(); // 初始化事件廣播器的bean信息 this.initApplicationEventMulticaster(); // 提供的一個(gè)空方法,供給子類(lèi)用于提供自定義的bean信息,或者修改已有的bean信息 this.onRefresh(); // 注冊(cè)事件監(jiān)聽(tīng)器 this.registerListeners(); // 對(duì)已經(jīng)注冊(cè)的非延遲(配置文件指定)bean的實(shí)例化 this.finishBeanFactoryInitialization(beanFactory); // 清除緩存的資源信息,初始化一些聲明周期相關(guān)的bean,并且發(fā)布Context已被初始化的事件 this.finishRefresh(); } catch (BeansException var10) { if (this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10); } // 發(fā)生異常則銷(xiāo)毀已經(jīng)生成的bean this.destroyBeans(); // 重置refresh字段信息 this.cancelRefresh(var10); throw var10; } finally { // 初始化一些緩存信息 this.resetCommonCaches(); contextRefresh.end(); } } }
1. 自動(dòng)加載配置類(lèi)
2. bean定義和注冊(cè)
注:springboot只是比spring多了自動(dòng)配置相關(guān)流程,在spring上做了一層邏輯封裝。
AbstractAutowireCapableBeanFactory為AutowireCapableBeanFactory接口的一個(gè)實(shí)現(xiàn)類(lèi),其中AbstractAutowireCapableBeanFactory實(shí)現(xiàn)類(lèi)的一個(gè)方法doCreateBean()
//位置:AbstractAutowireCapableBeanFactory#doCreateBean protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 實(shí)例化階段 instanceWrapper = this.createBeanInstance(beanName, mbd, args); } ... Object exposedObject = bean; try { // 依賴(lài)注入,屬性賦值階段 this.populateBean(beanName, mbd, instanceWrapper); // 初始化階段 exposedObject = this.initializeBean(beanName, exposedObject, mbd); } catch (Throwable var18) { ... } ... }
可以發(fā)現(xiàn),分別調(diào)用三種方法:
createBeanInstance() -> 實(shí)例化
populateBean() -> 依賴(lài)注入
initializeBean() -> 初始化
銷(xiāo)毀
銷(xiāo)毀階段是在容器關(guān)閉時(shí)調(diào)用的,在ConfigurableApplicationContext#close()
至于xxxAware,BeanPostProcessor,BeanFactoryPostProcessor等類(lèi),只不過(guò)是對(duì)主流程的一系列擴(kuò)展點(diǎn)而已。
Spring Bean 的生命周期的擴(kuò)展點(diǎn)很多,這里不可能全部列出來(lái),只說(shuō)核心的擴(kuò)展點(diǎn)。這也就是為什么 Spring 的擴(kuò)展性很好的原因,開(kāi)了很多的口子,盡可能讓某個(gè)功能高內(nèi)聚松耦合,用戶(hù)需要哪個(gè)功能就用哪個(gè),而不是直接來(lái)一個(gè)大而全的東西。
這些接口的實(shí)現(xiàn)類(lèi)是基于 Bean 的,只要實(shí)現(xiàn)了這些接口的Bean才起作用。
BeanNameAware
BeanFactoryAware
ApplicationContextAware
InitializingBean
DisposableBean
還要很多的xxxAware,這些不常用,下面生命周期測(cè)試就不加上,如:
BeanClassLoaderAware
EnvironmentAware
EmbeddedValueResolverAware
ResourceLoaderAware
ApplicationEventPublisherAware
MessageSourceAware
ServletContextAware
這些接口的實(shí)現(xiàn)類(lèi)是獨(dú)立于 Bean 的,并且會(huì)注冊(cè)到 Spring 容器中。一般稱(chēng)它們的實(shí)現(xiàn)類(lèi)為后置處理器。
在 Spring 容器創(chuàng)建任何 Bean 的時(shí)候,這些后置處理器都會(huì)發(fā)生作用
BeanPostProcessor
InstantiationAwareBeanPostProcessor(InstantiationAwareBeanPostProcessor 是繼承了 BeanPostProcessor)
工廠后處理器接口也是容器級(jí)的。在應(yīng)用上下文裝配配置文件之后立即調(diào)用:
AspectJWeavingEnabler
ConfigurationClassPostProcessor
CustomAutowireConfigurer
該類(lèi)是 BeanPostProcessor 的子接口,常用的有如下三個(gè)方法:
postProcessBeforeInstantiation(Class beanClass, String beanName):在bean實(shí)例化之前調(diào)用
postProcessProperties(PropertyValues pvs, Object bean, String beanName):在bean實(shí)例化之后、設(shè)置屬性前調(diào)用
postProcessAfterInstantiation(Class beanClass, String beanName):在bean實(shí)例化之后調(diào)用
BeanNameAware接口是為了讓自身Bean能夠感知到,只有一個(gè)方法setBeanName(String name),獲取到自身在Spring容器中的id或name屬性。
該接口只有一個(gè)方法setBeanFactory(BeanFactory beanFactory),用來(lái)獲取當(dāng)前環(huán)境中的 BeanFactory,可以對(duì)工廠中的所有bean進(jìn)行擴(kuò)展。
該接口只有一個(gè)方法setApplicationContext(ApplicationContext applicationContext),用來(lái)獲取當(dāng)前環(huán)境中的 ApplicationContext,可以對(duì)整個(gè)容器進(jìn)行擴(kuò)展。
注:有時(shí)候并不會(huì)調(diào)用該接口,這要根據(jù)你的IOC容器來(lái)決定:Spring IOC容器最低要求是實(shí)現(xiàn)BeanFactory接口,而不是實(shí)現(xiàn)ApplicationContext接口,對(duì)于那些沒(méi)有實(shí)現(xiàn)ApplicationContext接口的容器,在生命周期對(duì)應(yīng)的ApplicationContextAware定義的方法也是不會(huì)調(diào)用的,只要實(shí)現(xiàn)了ApplicationContext接口的容器,才會(huì)調(diào)用。
postProcessBeforeInitialization(Object bean, String beanName):在初始化之前調(diào)用此方法,Spring 的 AOP 就是利用它實(shí)現(xiàn)的。
postProcessAfterInitialization(Object bean, String beanName):在初始化之后調(diào)用此方法
該接口只有一個(gè)方法afterPropertiesSet(),在屬性注入完成后調(diào)用。
凡是繼承該接口的類(lèi),在初始化bean的時(shí)候都會(huì)執(zhí)行該方法,可以進(jìn)行一些屬性配置等工作。
InitializingBean 對(duì)應(yīng)生命周期的初始化階段,在源碼的invokeInitMethods(beanName, wrappedBean, mbd)方法中調(diào)用。
該接口的作用是在對(duì)象銷(xiāo)毀時(shí)調(diào)用,可以做一些資源銷(xiāo)毀操作。
DisposableBean 類(lèi)似于InitializingBean,對(duì)應(yīng)生命周期的銷(xiāo)毀階段,以ConfigurableApplicationContext#close()方法作為入口,實(shí)現(xiàn)是通過(guò)循環(huán)取所有實(shí)現(xiàn)了DisposableBean接口的Bean然后調(diào)用其destroy()方法
@Bean聲明一個(gè)bean,配合@Configuration注解使用
initMethod:聲明bean初始化時(shí)回調(diào)一個(gè)方法,該方法需要程序員編寫(xiě)
destroyMethod:聲明bean銷(xiāo)毀時(shí)回調(diào)一個(gè)方法,該方法需要程序員編寫(xiě)
bean的一個(gè)基于注解的初始化方法
bean的一個(gè)基于注解的銷(xiāo)毀方法
@Configuration public class BeanInitAndDestroyConfig { /** * @return 這里沒(méi)有指定bean名字,默認(rèn)是方法名 */ @Description("測(cè)試bean的生命周期") @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod") public MyService myServiceBeanName() {//入?yún)?shù)可注入其他依賴(lài) return new MyService(); } }
聲明一個(gè)名為:myServiceBeanName的bean
initMethod:bean的初始化方法為:initMethod
destroyMethod:bean的銷(xiāo)毀方法為:destroyMethod
這里只是想用來(lái)說(shuō)明 @Qualifier注解能根據(jù)bean名稱(chēng)匹配。
即是針對(duì)當(dāng)前bean只調(diào)用一次的接口
/** * @Description: bean生命周期測(cè)試:這些接口只針對(duì)當(dāng)前bean * @Author: jianweil * @date: 2021/12/8 9:46 */ public class MyService implements Person, BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean { private Animal animal = null; private ApplicationContext applicationContext; /** *接口規(guī)定方法 */ @Override public void service() { this.animal.use(); } public MyService() { System.out.println("2. [bean實(shí)例化]:"+this.getClass().getSimpleName()+"----------構(gòu)造方法"); } /** *接口規(guī)定方法:注入依賴(lài) */ @Override @Autowired @Qualifier("dog") public void setAnimal(Animal animal) { System.out.println("5. [bean屬性賦值]:dog----依賴(lài)注入"); this.animal = animal; } @Override public void setBeanName(String s) { System.out.println("6. 調(diào)用【BeanNameAware】--setBeanName:"+s); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("7. 調(diào)用【BeanFactoryAware】--setBeanFactory"); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; System.out.println("8. 調(diào)用【ApplicationContextAware】--setApplicationContext"); } /** * 初始化1 */ @PostConstruct public void myInit() { System.out.println("10. [初始化] 注解@PostConstruct自定義初始化方法[myInit]"); } /** * 初始化2 */ @Override public void afterPropertiesSet() throws Exception { System.out.println("11. [初始化] 接口InitializingBean方法[afterPropertiesSet]"); } /** * 初始化3 */ public void initMethod() { System.out.println("12. [初始化] 注解@Bean自定義初始化方法[initMethod]"); } /** * 銷(xiāo)毀1 */ @PreDestroy public void myDestroy() { System.out.println("14. [銷(xiāo)毀] 注解@PreDestroy自定義銷(xiāo)毀方法[myDestroy]"); } /** * 銷(xiāo)毀2 */ @Override public void destroy() throws Exception { System.out.println("15. [銷(xiāo)毀] 接口DisposableBean方法[destroy]"); } /** * 銷(xiāo)毀3 */ public void destroyMethod() { System.out.println("16. [銷(xiāo)毀] 注解@Bean自定義銷(xiāo)毀方法[destroyMethod]"); } }
這里實(shí)現(xiàn)的接口只作用于當(dāng)前bean(即是上面@bean定義的bean名為myDefineBeanName)生命周期
每個(gè)bean生命周期都執(zhí)行一次
后置處理器是作用于ioc容器中所有bean的生命周期。
/** * @Description: todo * @Author: jianweil * @date: 2021/12/20 17:20 */ @Component public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) { System.out.println("============================InstantiationAwareBeanPostProcessor-開(kāi)始======================"); System.out.println("1. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName為"+beanName); } return null; } @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) { System.out.println("3. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName為"+beanName); } return true; } @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) { System.out.println("4. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName為"+beanName); System.out.println("============================InstantiationAwareBeanPostProcessor-結(jié)束======================"); } return null; } }
/** * @Description: 后置bean的初始化器:所有的bean都會(huì)攔截執(zhí)行 * @Author: jianweil * @date: 2021/12/8 9:46 */ @Component public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { //這里過(guò)濾掉springboot自動(dòng)配置的bean,只打印我們項(xiàng)目的bean情況 if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) { System.out.println("9. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName為" + beanName); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) { System.out.println("13. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName為" + beanName); } return bean; } }
容器級(jí)別,只允許一次
@Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { System.out.println("0. [容器級(jí)別只調(diào)用一次] 調(diào)用 BeanFactoryPostProcessor.postProcessBeanFactory() 方法"); } }
“//”標(biāo)記為解讀
//容器級(jí)別的工廠后置處理器,只在應(yīng)用上下文裝配配置文件之后立即調(diào)用1次 0. [容器級(jí)別只調(diào)用一次] 調(diào)用 BeanFactoryPostProcessor.postProcessBeanFactory() 方法 //因?yàn)槲覀兩^(guò)程只打印("myServiceBeanName".equals(beanName) || "dog".equals(beanName)),所有貓只有構(gòu)造方法打印了 貓----------構(gòu)造方法 //###############################dog的生命周期############################################### //后置處理器,容器級(jí)別,作用于所有bean ============================InstantiationAwareBeanPostProcessor-開(kāi)始====================== 1. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName為dog //狗的實(shí)例化 狗----------構(gòu)造方法 //后置處理器,容器級(jí)別,作用于所有bean 3. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName為dog //后置處理器,容器級(jí)別,作用于所有bean 4. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName為dog ============================InstantiationAwareBeanPostProcessor-結(jié)束====================== //后置處理器,容器級(jí)別,作用于所有bean 9. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName為dog //后置處理器,容器級(jí)別,作用于所有bean 13. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName為dog //###############################dog的bean完成,開(kāi)始myServiceBeanName############################################### //后置處理器,容器級(jí)別,作用于所有bean ============================InstantiationAwareBeanPostProcessor-開(kāi)始====================== 1. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() 方法:beanName為myServiceBeanName //實(shí)例化 2. [bean實(shí)例化]:MyService----------構(gòu)造方法 //后置處理器,容器級(jí)別,作用于所有bean 3. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation() 方法:beanName為myServiceBeanName //后置處理器,容器級(jí)別,作用于所有bean 4. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 InstantiationAwareBeanPostProcessor.postProcessProperties() 方法:beanName為myServiceBeanName ============================InstantiationAwareBeanPostProcessor-結(jié)束====================== //屬性賦值,即是依賴(lài)注入 5. [bean屬性賦值]:dog----依賴(lài)注入 //bean級(jí)別,bean:myServiceBeanName實(shí)現(xiàn)了接口BeanNameAware 6. 調(diào)用【BeanNameAware】--setBeanName:myServiceBeanName //bean級(jí)別 7. 調(diào)用【BeanFactoryAware】--setBeanFactory //bean級(jí)別 8. 調(diào)用【ApplicationContextAware】--setApplicationContext //后置處理器,容器級(jí)別,作用于所有bean:初始化前處理 9. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 BeanPostProcessor.postProcessBeforeInitialization 方法:beanName為myServiceBeanName //初始化 10. [初始化] 注解@PostConstruct自定義初始化方法[myInit] 11. [初始化] 接口InitializingBean方法[afterPropertiesSet] 12. [初始化] 注解@Bean自定義初始化方法[initMethod] //后置處理器,容器級(jí)別,作用于所有bean:初始化后處理 13. [容器級(jí)別每個(gè)bean都回調(diào)] 調(diào)用 BeanPostProcessor.postProcessAfterInitialization 方法:beanName為myServiceBeanName //容器環(huán)境加載完成,這時(shí)可以使用所有bean 2021-12-21 11:18:42.994 INFO 18956 --- [ main] c.l.s.SpringbootBeanLifecycleApplication : Started SpringbootBeanLifecycleApplication in 0.719 seconds (JVM running for 1.312) //銷(xiāo)毀 14. [銷(xiāo)毀] 注解@PreDestroy自定義銷(xiāo)毀方法[myDestroy] 15. [銷(xiāo)毀] 接口DisposableBean方法[destroy] 16. [銷(xiāo)毀] 注解@Bean自定義銷(xiāo)毀方法[destroyMethod] Process finished with exit code 0
了解 Spring 生命周期的意義就在于,可以利用 Bean 在其存活期間的指定時(shí)刻完成一些相關(guān)操作。一般情況下,會(huì)在 Bean 被初始化后和被銷(xiāo)毀前執(zhí)行一些相關(guān)操作。
上述內(nèi)容就是怎么深入了解Spring的Bean生命周期,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。