模仿Spring手寫一個(gè)簡(jiǎn)易的IOC
這個(gè)小項(xiàng)目是我讀過(guò)一點(diǎn)Spring的源碼后,模仿Spring的IOC寫的一個(gè)簡(jiǎn)易的IOC,當(dāng)然Spring的在天上,我寫的在馬里亞納海溝,哈哈
感興趣的小伙伴可以去我的github拉取代碼看著玩
地址: https://github.com/zhuchangwu/CIOC
項(xiàng)目中有兩種方式實(shí)現(xiàn)IOC:
- 第一種是基于dom4j實(shí)現(xiàn)的解析XML配置文件版
- 第二種是基于自定義注解實(shí)現(xiàn)全配置版
全注解版
模仿Spring原生的IOC機(jī)制如下:
- Interface類型的beanDefinition不會(huì)被實(shí)例化**
- String類型的beanDefinition不會(huì)被實(shí)例化
- 維護(hù)三個(gè)核心的map容器
使用底層存放實(shí)例化對(duì)象的容器是一個(gè)叫singletonObjects的CurrentHashMap
第二個(gè)用來(lái)輔助解決循環(huán)依賴的容器叫singletonFactories類型:CurrentHashMap
第三個(gè)用來(lái)存放bean定義信息的map容器叫beanDefinitionMap類型:CurrentHashMap
Spring底層的自己還封裝了BeanDefinition, 當(dāng)然我沒(méi)干這件事,直接用的類的描述對(duì)象 Class
自定義了四種注解如下:
CDao 用于標(biāo)識(shí)持久層的對(duì)象
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface CDao { String value()default ""; }
CService 用來(lái)標(biāo)識(shí)服務(wù)層的對(duì)象
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface CService { String value()default ""; }
CComponentScan 用來(lái)標(biāo)識(shí)主配置類,提供包掃描需要的base-packet
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface CComponentScan { String value()default ""; }
CAutowired 用來(lái)標(biāo)識(shí)需要自動(dòng)裝配的對(duì)象
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface CAutowired { String value()default ""; }
當(dāng)然他跟Spring原生的@Autowired是沒(méi)法比的,Spring自動(dòng)裝配類型默認(rèn)是Autowired_no, 但是被Spring原生標(biāo)記上的對(duì)象會(huì)先按照默認(rèn)的裝配類型進(jìn)行裝配,如果沒(méi)有默認(rèn)的裝配類型,再按照byType,如果容器中存在多個(gè)相同類型的對(duì)象,就按照byName, 名字再一樣就直接報(bào)錯(cuò)了
另外我說(shuō)一下,說(shuō)了這么多byName和byType, 那么byName,是通過(guò)哪個(gè)name呢? 如果是基于setter方法的話就是setter去掉set后,后面的名字, 如果是通過(guò)@Autowired的byName,這個(gè)name其實(shí)就是屬性名
Spring是允許程序員去改這個(gè)默認(rèn)的裝配類型的
然后在我的IOC中就比較遜色了,直接默認(rèn)按照byType,沒(méi)有合適的類型再按照byName進(jìn)行自動(dòng)裝配
解決了循環(huán)依賴的問(wèn)題
在我手動(dòng)寫如何解決循環(huán)依賴的時(shí)候,那時(shí)候我還沒(méi)有去看源碼, 當(dāng)時(shí)我畫了幾個(gè)流程圖,但是還是卡殼了, 于是我去調(diào)試Spring的實(shí)現(xiàn), 簡(jiǎn)直了!Spring的作者們簡(jiǎn)直是真神!
其實(shí)說(shuō)Spring如何解決循環(huán)依賴的,我前面有幾個(gè)源碼閱讀的博客,感興趣可以去看看
這里我就簡(jiǎn)單的說(shuō)下, 這件事是一個(gè)叫AutowiredAnnotationBeanDefinitonPostprocessor的后置處理器完成的, Spring在做這件事是時(shí)候,前前后后是一個(gè)偌大的繼承體系在支持,但是歸根結(jié)底是Spring玩了個(gè)漂亮的遞歸,方法名是getBean(),當(dāng)然這個(gè)遞歸還有幾個(gè)輔助容器,這幾個(gè)容器就是我上面說(shuō)的幾個(gè)map ,我的IOC能寫成,就得益于這一點(diǎn)
XML版
注解版的IOC我是用DOM4j解析XML配置文件實(shí)現(xiàn)的, 做了下面的功能
支持setter方法依賴注入
標(biāo)識(shí)性的信息是 property
<bean id="dao1" class="com.changwu.dao.DaoImpl1"></bean> <bean id="service" class="com.changwu.service.UserServiceImpl4"> <property ref="dao1" name="daoImpl"></property> </bean>
支持構(gòu)造方法的依賴注入
標(biāo)識(shí)性的信息是 constructor-arg
<bean id="DaoImpl" class="com.changwu.dao.DaoImpl1"></bean> <bean id="service" class="com.changwu.service.UserServiceImpl3"> <constructor-arg ref ="DaoImpl" name="DaoImpl1"></constructor-arg> </bean> </bean>
支持byType的自動(dòng)裝配
標(biāo)識(shí)性的信息是 byType
<beans default-autowire="byType">
主持byName的自動(dòng)裝配
<beans default-autowire="byName">
以上就是模仿Spring手寫一個(gè)簡(jiǎn)易的IOC的詳細(xì)內(nèi)容,更多關(guān)于手寫IOC的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java?SpringBoot注解@Async不生效的解決方法
大家好,本篇文章主要講的是java?SpringBoot注解@Async不生效的解決方法,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-01-01java 實(shí)現(xiàn)隨機(jī)數(shù)組輸出及求和實(shí)例詳解
這篇文章主要介紹了java 實(shí)現(xiàn)隨機(jī)數(shù)組輸出及求和實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2016-11-11Java數(shù)據(jù)結(jié)構(gòu)之循環(huán)隊(duì)列簡(jiǎn)單定義與用法示例
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)之循環(huán)隊(duì)列簡(jiǎn)單定義與用法,簡(jiǎn)要描述了循環(huán)隊(duì)列的概念、原理,并結(jié)合實(shí)例形式分析了java循環(huán)隊(duì)列的定義與使用方法,需要的朋友可以參考下2017-10-10java中基本注解的知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整理的是一篇關(guān)于java中基本注解的知識(shí)點(diǎn)總結(jié),有需要的朋友們可以跟著學(xué)習(xí)下。2021-06-06談?wù)剬?duì)Java多態(tài)性的一點(diǎn)理解
多態(tài)就是指程序中定義的引用變量所指向的具體類型和通過(guò)該引用變量發(fā)出的方法調(diào)用在編程時(shí)并不確定,而是在程序運(yùn)行期間才確定,即一個(gè)引用變量倒底會(huì)指向哪個(gè)類的實(shí)例對(duì)象,該引用變量發(fā)出的方法調(diào)用到底是哪個(gè)類中實(shí)現(xiàn)的方法,必須在由程序運(yùn)行期間才能決定2017-08-08