1. 程式人生 > 程式設計 >模仿Spring手寫一個簡易的IOC

模仿Spring手寫一個簡易的IOC

這個小專案是我讀過一點Spring的原始碼後,模仿Spring的IOC寫的一個簡易的IOC,當然Spring的在天上,我寫的在馬裡亞納海溝,哈哈

感興趣的小夥伴可以去我的github拉取程式碼看著玩

地址: https://github.com/zhuchangwu/CIOC

專案中有兩種方式實現IOC:

  • 第一種是基於dom4j實現的解析XML配置檔案版
  • 第二種是基於自定義註解實現全配置版

全註解版

模仿Spring原生的IOC機制如下:

  • Interface型別的beanDefinition不會被例項化**
  • String型別的beanDefinition不會被例項化
  • 維護三個核心的map容器

使用底層存放例項化物件的容器是一個叫singletonObjects的CurrentHashMap

第二個用來輔助解決迴圈依賴的容器叫singletonFactories型別:CurrentHashMap
第三個用來存放bean定義資訊的map容器叫beanDefinitionMap型別:CurrentHashMap
Spring底層的自己還封裝了BeanDefinition,當然我沒幹這件事,直接用的類的描述物件 Class

自定義了四種註解如下:

CDao 用於標識持久層的物件

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface CDao {
  String value()default "";
}

CService 用來標識服務層的物件

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface CService {
  String value()default "";
}

CComponentScan 用來標識主配置類,提供包掃描需要的base-packet

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface CComponentScan {
  String value()default "";
}

CAutowired 用來標識需要自動裝配的物件

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CAutowired {
  String value()default "";
}

當然他跟Spring原生的@Autowired是沒法比的,Spring自動裝配型別預設是Autowired_no,但是被Spring原生標記上的物件會先按照預設的裝配型別進行裝配,如果沒有預設的裝配型別,再按照byType,如果容器中存在多個相同型別的物件,就按照byName,名字再一樣就直接報錯了

另外我說一下,說了這麼多byName和byType,那麼byName,是通過哪個name呢? 如果是基於setter方法的話就是setter去掉set後,後面的名字,如果是通過@Autowired的byName,這個name其實就是屬性名

Spring是允許程式設計師去改這個預設的裝配型別的

然後在我的IOC中就比較遜色了,直接預設按照byType,沒有合適的型別再按照byName進行自動裝配

解決了迴圈依賴的問題

在我手動寫如何解決迴圈依賴的時候,那時候我還沒有去看原始碼,當時我畫了幾個流程圖,但是還是卡殼了,於是我去除錯Spring的實現,簡直了!Spring的作者們簡直是真神!
其實說Spring如何解決迴圈依賴的,我前面有幾個原始碼閱讀的部落格,感興趣可以去看看

這裡我就簡單的說下,這件事是一個叫AutowiredAnnotationBeanDefinitonPostprocessor的後置處理器完成的,Spring在做這件事是時候,前前後後是一個偌大的繼承體系在支援,但是歸根結底是Spring玩了個漂亮的遞迴,方法名是getBean(),當然這個遞迴還有幾個輔助容器,這幾個容器就是我上面說的幾個map,我的IOC能寫成,就得益於這一點

XML版

註解版的IOC我是用DOM4j解析XML配置檔案實現的,做了下面的功能

支援setter方法依賴注入
標識性的資訊是 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>

支援構造方法的依賴注入

標識性的資訊是 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的自動裝配
標識性的資訊是 byType

<beans default-autowire="byType">

主持byName的自動裝配

<beans default-autowire="byName">

以上就是模仿Spring手寫一個簡易的IOC的詳細內容,更多關於手寫IOC的資料請關注我們其它相關文章!