通過spring源碼的學(xué)習(xí),可以知道spring中擁有很多的拓展,其中有BeanDefinitionRegistryPostProcessor類型類的拓展
在spring加載的時(shí)候椒功,會(huì)去判斷是否擁有BeanDefinitionRegistryPostProcessor類型的類华烟,若是擁有則會(huì)執(zhí)行繼承這個(gè)類的postProcessBeanDefinitionRegistry()方法,以及postProcessBeanFactory()方法酿矢,其中在這兩個(gè)方法中榨乎,擁有參數(shù)BeanDefinitionRegistry(BeanDefinition注冊(cè)器),以及ConfigurableListableBeanFactory(bean工廠)瘫筐,一旦擁有了這兩個(gè)參數(shù)蜜暑,那咱們就能對(duì)spring容器進(jìn)行操作了。
大致講一下spring加載的一個(gè)流程策肝,在這就不細(xì)說了肛捍,細(xì)說的話隐绵,我覺得我可以碼一本小說了。(在此細(xì)說拙毫,僅僅是為了裝個(gè)小B)
首先spring加載的時(shí)候氢橙,會(huì)將匹配到的.class文件全都轉(zhuǎn)化為BeanDefinition,存放到一個(gè)集合中。即:beanDefinitionMap恬偷。
然后在beanfactory在getbean()的時(shí)候悍手,將beanDefinitionMap拿到,接著生成實(shí)例袍患,放到一個(gè)容器坦康,即:singletonObjects? ?可以將它稱為:一級(jí)緩存。
對(duì)于spring來說诡延,他的開閉原則是他的精髓思想滞欠,里面內(nèi)置了很多拓展,因此咱們可以利用這些拓展來對(duì)spring的ioc容器進(jìn)行操作肆良。比如:在還沒加入到ioc容器之前筛璧,咱們可以自定義一些BeanDefinition,通過BeanDefinition注冊(cè)器將它放入到BeanDefinition這個(gè)map中惹恃,這樣就能實(shí)現(xiàn)ioc的注入了夭谤。
另外在注解掃描的時(shí)候,有個(gè)特有的類巫糙,importselect朗儒,在掃描到的時(shí)候,也會(huì)執(zhí)行importselect方法参淹,我們也可以通過繼承importselect來實(shí)現(xiàn)BeanDefinition的注入醉锄。
既然有了能操作BeanDefinition注冊(cè)器,以及BeanFactory浙值,那接下來就可以通過讀取到配置文件中的內(nèi)容恳不,將它注入到ioc容器中了。
以下我會(huì)用三種方式去實(shí)現(xiàn)开呐。
在操作之前烟勋,先看一下配置文件的設(shè)置
第一種:操作postProcessBeanDefinitionRegistry()
第二種:操作postProcessBeanFactory()
因?yàn)樾枰O(shè)置beanName,考慮到首字母小寫负蚊,因此單獨(dú)拿出來一個(gè)方法去實(shí)現(xiàn)
這兩種方式神妹,都是通過操作同一個(gè)類的,只不過通過操作兩個(gè)方法去實(shí)現(xiàn)家妆,但是功能可以說是一樣的鸵荠,都是通過拿到配置文件的內(nèi)容,然后將它變?yōu)锽eanDefinition伤极,然后加入到beanfactory的BeanDefinition集合中蛹找。
第三種:
這個(gè)方法相對(duì)而言有點(diǎn)騷姨伤。主要用到@Import方法,通過拿到@import方法中的注解中的參數(shù)庸疾,拿到配置文件對(duì)應(yīng)的內(nèi)容乍楚,然后拿到類的全限定類名接著返回。
個(gè)人而言届慈,這種方式拓展性更強(qiáng)徒溪,可以通過jar包的方式,導(dǎo)入金顿,然后在自己項(xiàng)目中設(shè)置配置文件導(dǎo)入自己需要指定的的類臊泌。
接下來咱們看一下,這個(gè)@Import是在那使用的揍拆。這邊是用了一個(gè)注解去導(dǎo)入渠概。
通過這樣的方式導(dǎo)入,用來實(shí)現(xiàn)三種方式的spi技術(shù)嫂拴。這塊功能也完全可以將他變?yōu)橐粋€(gè)jar包播揪,導(dǎo)入到其他項(xiàng)目中使用。
通過一個(gè)簡(jiǎn)簡(jiǎn)單單的注解筒狠,就能實(shí)現(xiàn)了jar包項(xiàng)目中的類導(dǎo)入了猪狈。
有人可能會(huì)說:@ComponentScan注解不是更方便么?確實(shí)窟蓝,@ComponentScan這個(gè)注解很方便罪裹,而且也完全是無腦的,但是為啥我還要用這種spi的技術(shù)去實(shí)現(xiàn)的运挫。說實(shí)話:我就是為了裝逼。裝逼使我快樂套耕,裝逼使我開心谁帕,我裝逼,我驕傲冯袍。
有興趣的可以將這個(gè)項(xiàng)目拉下來看一下匈挖。
https://github.com/young287/spring_spi_demo 這個(gè)是項(xiàng)目地址。
https://github.com/young287/spring5.2.8_yuanma 這個(gè)是spring5.2.8源碼的地址康愤,里面是我學(xué)習(xí)了源碼以后儡循,在源碼里面寫的一些注解,有興趣的小伙伴也可以下載下來看看征冷。
一起努力吧择膝,咱們是目標(biāo)不是星辰大海,而是懟死面試官检激。