從LF的初始化加載來(lái)探究Spring生命周期
在社區(qū)里碰到過(guò)好幾次小伙伴運(yùn)行的Demo報(bào)找不到注冊(cè)節(jié)點(diǎn)的問(wèn)題。經(jīng)過(guò)查看發(fā)現(xiàn)都是對(duì)于Spring生命周期理解的問(wèn)題。
LF在在Springboot自動(dòng)裝配過(guò)程中,對(duì)于節(jié)點(diǎn)的掃描和規(guī)則的初始化是不同的生命周期。正常的順序都應(yīng)該是:先注冊(cè)節(jié)點(diǎn)再初始化規(guī)則。如果出現(xiàn)了先初始化規(guī)則,再注冊(cè)節(jié)點(diǎn),就會(huì)出現(xiàn)問(wèn)題。
LF的Springboot的自動(dòng)裝配主要用到了Spring的兩個(gè)生命周期。
第一個(gè)是BeanPostProcessor,這個(gè)階段在受spring管理的bean初始化的前后,所以這個(gè)接口分為初始化前和初始化后兩個(gè)實(shí)現(xiàn)。LF是利用了初始化后這個(gè)生命周期來(lái)對(duì)所有的組件進(jìn)行初始化。這個(gè)生命周期在整個(gè)spring生命周期相對(duì)中間的位置。
第二個(gè)是SmartInitializingSingleton,這個(gè)階段在所有受spring管理單例對(duì)象(非懶加載)初始化完成之后進(jìn)行回調(diào)。LF是利用了所有的單例Bean都初始化好后這個(gè)生命周期來(lái)去解析定義好規(guī)則(包括項(xiàng)目?jī)?nèi)的和其他存儲(chǔ)里的),這個(gè)生命周期在整個(gè)spring生命周期相對(duì)靠后的位置。
所以,對(duì)于普通的掃描節(jié)點(diǎn)來(lái)說(shuō),因?yàn)長(zhǎng)F已經(jīng)嚴(yán)格控制了生命周期,所以不會(huì)出現(xiàn)問(wèn)題。
凡是出問(wèn)題的場(chǎng)景都是使用者自己利用代碼去注冊(cè)節(jié)點(diǎn)/鏈路,但使用者沒有選對(duì)正確的生命周期。
舉個(gè)最簡(jiǎn)單的例子,使用者用代碼方式去額外定義規(guī)則。想要在系統(tǒng)啟動(dòng)時(shí)去運(yùn)行一段代碼,其實(shí)方式太多了。但是如果你使用在一個(gè)bean里用@PostConstruct注解去做這件事情,就有可能出現(xiàn)問(wèn)題。
圖片
從圖上可以看到,@PostConstruct這個(gè)注解是在初始化bean的過(guò)程中執(zhí)行,由于bean是一個(gè)個(gè)進(jìn)入BeanPostProcessor這個(gè)生命周期的,如果使用者在這個(gè)周期里去定義鏈路并解析,由于鏈路所用到的節(jié)點(diǎn)很可能還未被初始化好,所以這時(shí)候就會(huì)報(bào)找不到節(jié)點(diǎn)的錯(cuò)誤。
正確的做法是,使用者也去定義一個(gè)類,實(shí)現(xiàn)SmartInitializingSingleton或者去實(shí)現(xiàn)CommandLineRunner,利用這兩個(gè)比較靠后的生命周期去定義額外的規(guī)則。
推薦是采用更靠后的CommandLineRunner去定義,這個(gè)生命周期比SmartInitializingSingleton還要往后。非常適合用來(lái)做啟動(dòng)系統(tǒng)后的一系列自定義業(yè)務(wù)。
同理,如果你在static塊中去定義規(guī)則,或是在構(gòu)造方法里去定義規(guī)則,其生命周期和@PostConstruct差不多。
再比如,你在CommandLineRunner里用代碼去定義額外節(jié)點(diǎn)。也是不行的,因?yàn)镃ommandLineRunner在SmartInitializingSingleton之后,等于說(shuō)解析規(guī)則在注冊(cè)你自己額外節(jié)點(diǎn)之前,如果規(guī)則里寫了額外注冊(cè)的節(jié)點(diǎn)的話,那么也會(huì)報(bào)找不到節(jié)點(diǎn)。
總的方針就是:規(guī)則的定義和解析一定要在節(jié)點(diǎn)注冊(cè)之后。
在Spring中可供擴(kuò)展的生命周期有很多。所以當(dāng)開發(fā)者想要在系統(tǒng)啟動(dòng)時(shí)額外做一些事情,有很多種選擇,但是開發(fā)者一定要清楚你的這個(gè)觸發(fā)時(shí)機(jī)是在整個(gè)生命周期的哪一步。
我之前整理過(guò)整個(gè)Spring啟動(dòng)過(guò)程的完整生命周期圖,這次我用紅框標(biāo)明了LF框架在注冊(cè)節(jié)點(diǎn)和解析規(guī)則所使用的兩個(gè)生命周期的相對(duì)位置。
圖片
其中每一個(gè)生命周期的講解在之前我寫的一篇文章中也有詳細(xì)解析,這里附上鏈接:
Springboot啟動(dòng)擴(kuò)展點(diǎn)超詳細(xì)總結(jié),再也不怕面試官問(wèn)了
LF CLUB
LF CLUB是由作者創(chuàng)辦的高級(jí)付費(fèi)社區(qū)。
LF CLUB能幫助到所有LiteFlow框架的使用者,以及想使用LiteFlow的潛在開發(fā)者。