爲seed容器添加自動注入和AOP功能

img

前言

  大概在半年前寫了一個簡陋的ioc容器,並設想實現不少功能,不過以後由於各類緣由(主要是懶( ̄▽ ̄)")閒置了。最近又從新將這個項目拾起,經過半個多月上班摸魚時間更新了兩個版本0.0.2(實現自動注入)和0.0.3(實現AOP),這篇博客就簡單講講實現的一些過程,分享給你們。源碼地址java

自動注入

大體流程圖:
git

img

  自動注入實現思路比較簡單,在bean建立完成後查看有哪些須要注入的屬性,利用beanPostProcessor來對bean進行處理,注入須要的屬性。目前seed容器支持 @Autowired注入當前bean中的類,以及 @Value注入默認值和 seed.yml/ seed.properties(當前seed容器環境變量environment)中的屬性(當前還不可以和spring同樣支持複雜的方法等表達式)。主要功能其實就只有兩塊:

  1. 解析yml文件。
  2. 判斷某個類是否符合注入須要(須要考慮到泛型)。

  解析yml比較簡單,因爲yml文件頗有特色。實現了YmlProperties用於讀取yml文件(參考了Properties類)。實現HashTable來存儲讀取的屬性值鍵值對。經過逐行讀取文件,利用yml文件明顯的特色:空格來表示所屬分級,來判斷出當前所屬節點以及上級節點,將全部屬性讀取成spring.aop(每一級用·分隔)格式的key,再利用的分隔符來獲取value。在seed容器初始化的時候將屬性加入到容器中。github

  判斷某個類的是否符合注入需求作起來仍是走了一些彎路。其實實現起來也不難,首先須要注入的類必定同級類或者父類。只要找到容器中每一個bean的實現或繼承類所對應的泛型關係就能夠了,經過二者對應的泛型關係來比較是否爲相同的類。web

AOP

  AOP功能的實現也是依賴的BeanPostProcessor。主要功能點在建立jdk以及cglib代理類和切入點的讀取處理。實現仍是參考的spring,在建立代理類的時候利用攔截器鏈來在方法執行先後進行處理。不論是建立jdk的代理類仍是建立cglib的代理類都會給處理器設置一個攔截器鏈,裏面放置着匹配該類的攔截器,以後執行代理類方法的時候會匹配攔截器並逐一執行攔截器。
AOP抽象層的建模:
spring

img

  首先講下建立代理類遇到的一些問題吧,JDK的代理類建立比較簡單直接調用java的api就行。cglib就有些問題了,因爲是直接建立的新類,因此若是原先的類若是沒有無參的構造函數就須要調用有參構造函數,那麼就要在建立代理對象時注入構造函數參數。我這邊的處理方式是獲取第一個構造函數傳入的null參數。(其實和spring相似,因爲spring本身實現了cglib,因此它在建立代理對象的時候不須要調用構造函數。)這邊使用空參數並會有帶來什麼影響,由於最終調用原始方法的仍是容器建立的對象,而不是代理對象。(這是在實現cglib的MethodInterceptor時處理的)。可是若是建立對象的構造函數對參數進行了判斷而且拋異常,那建立代理對象就會出錯,暫時尚未什麼好的方案修復這一點,這也許就是spring使用本身的方式來實現cglib代理對象建立的緣由吧。數據庫

  在完成建立一個帶有攔截器鏈的代理類以後遇到的問題就是如何匹配切點表達式。原先是想本身實現的,然而本身光是寫匹配包名的表達式就花了好幾個小時,因而果斷放棄了(lll¬ω¬)。而後看了下spring是如何處理的,結果發現spring是使用了aspectjweaver這個jar包來處理的。以後便在aop模塊導入了該jar包,參考了spring的使用方式,完成了對切面表達式的匹配。(因此@Aspect,@Before等註解都是使用的該jar包的)。api

  在完成編碼以後趕忙測試了一下AOP的功能,發現徹底OK,說實話仍是有點小激動的,就目前使用來看和Spring的幾乎沒有什麼差異,能夠說徹底契合麻雀雖小,五臟俱全這句話了。不過仔細想一想在實現AOP的時候也沒有太多難點,主要仍是在思路上。我雖然實現方式有差異,可是大體思路仍是模仿Spring,仍是得感嘆下Spring設計師超前的思路。框架

總結

  完成了自動注入和AOP以後能夠說seed做爲一個bean容器來講已經比較完善了。以後應該會爲該項目添加更多功能,例如數據庫交互,web交互等等。該項目仍是可以幫助我更好的理解框架內部的一些原理的。最後我但願本身的項目能夠幫助到你們。(若是有志同道合的小夥伴咱們能夠一塊兒寫一些比較好玩的項目O(∩_∩)O)函數

相關文章
相關標籤/搜索