天天看點

自己實作spring核心功能 一

自己實作spring核心功能 一

聊聊spring

spring對于java開發者來說,是最熟悉不過的架構了,我們日常開發中每天都在使用它。它有着各種各樣的好處,簡單易用,得心應手... ...
           

我們一說到spring就會講到ioc 、aop、依賴注入,注解等專業名詞,不少剛接觸java的人,都是一頭霧水,很難直覺的去了解這些是個什麼玩意,但使用的多了 就愛上了它給我們帶來的便利。

探索spring

當我們熟練的使用它之後就會好奇,ioc怎麼實作的呢?為什麼我隻要在類的變量中加入@AutoWrited 就能使用這個變量?帶着疑惑我們就會開始翻源碼,找答案。經過一番努力,最終我們定位到了spring-context.jar包,找到了
           

AbstractApplicationContext對象的refresh方法,這裡面的實作和步驟,就是整個spring功能的核心,裡面的實作另我們歎為觀止,但也相當之複雜,用到了很大設計模式,難以窺見全貌,很多地方的設計我們不知道為啥需要這麼實作。但我們還是知道了ioc容器實際上是用的Hashmap,

依賴注入使用的是反射,aop實際上是動态代理完成的。還有很大一部分代碼看的有點暈,就是加強健壯性保證生命周期和各種特性的。不管怎麼說,那都是别人的東西,我們隻會用,源碼我們看了很多,但很少自己來實作出來。

spring實作分析

不管怎麼說,别人的實作是别人的,自己寫出來的東西是屬于我們自己的。既然下決心要自己也能實作了,那我們就需要分析分析了。

spring怎麼做到代碼侵入量少且各層級分明的呢?

     spring采用約定大于配置,按照固定模式,層級分為Controller 、Service、Component、Bean、Configuration來辨別類型

  spring是怎麼管理依賴關系的?

      是通過注解或xml

  spring是怎麼發現哪些類需要管理的?

      是注解标記+包路徑掃描

  spring是如何實作依賴注入的?

     通過AutoWrited注解标記加反射執行個體化對象

  spring是如何管理Bean的?

     使用HashMap容器、Set容器實作單例Bean

  spring怎麼實作aop切面的呢?

     使用動态代理的方式,并提供了cglib和jdk預設實作兩種方式

  spring是在何時加載到記憶體中的呢?

     springMvc是通過web.xml配置入口觸發,springboot是通過springApplication初始化觸發
           

本次實作spring核心功能會涉及到哪些點?

1.注解的定義與使用

  2.容器的初始化

  3.配置檔案的讀取與使用

  4.sevlet的使用

  5.注解的定義與使用

  6.反射的運用

  7.url路由與方法映射

  8.參數解析與綁定

  9.正則與轉義
           

正式開始

首先建立一個maven項目,代碼結構如下:

添加jar包依賴:

裡面有2個jar包加一個插件

1

javax.servlet-api.jar 用來啟動核心代碼和處理請求

fastjson.jar 用來做json參數綁定

jetty-maven-plugin 使用jetty作為web容器啟動

完整maven代碼如下:

View Code

建立前端控制器類

前端控制器專門處理servlet請求,比對到對應的方法執行後傳回,前端控制器是什麼可以參考我的另一篇部落格《SpringMvc請求處理流程與源碼探秘》

這裡我們建立一個叫CJDispatcherServlet的類,它繼承HttpServlet類,并且重寫HttpServlet的init(),doGet(),doPost() 這3個方法,圖中的HomeService和StudentService可以先忽略不寫

配置web.xml

需要配置 和 2個标簽

中需要

1.指定servlet名稱

2.指定處理請求的前端控制器類

3.設定初始化配置檔案路徑

完整web.xml檔案如下:

View Code

添加注解

我們知道,spring裡面是通過給類加注解來識别各種使用場景的,那我們就來實作幾個必用的

作用在類上的:

JCController

JCService

JCComponent

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

public @interface JCController {

String value() default  "";           

}

全部采用這種類型

作用在方法上和類上的:

JCRequestMapping

@Target({ElementType.TYPE,ElementType.METHOD})

public @interface JCRequestMapping {

String value() default "";           

作用在字段上的:

JCAutoWrited

@Target(ElementType.FIELD)

public @interface JCAutoWrited {

String value() default "";           

到此我們已經初步的建立完了需要準備的類,準備工作告一段落。

由于篇幅有限,下一篇開始實作核心功能了!

完整代碼位址

原文位址

https://www.cnblogs.com/jingch/p/11368982.html