在這篇小文章中,我將嘗試解釋為什麼我創建這個庫?以及它是如何實現的?
我在許多專案中使用了Java EE 框架,其中大多數專案運行應用程式的可用資源沒有限制,但在極少數情況下,我們的資源有限,尤其是在部署服務上部署應用程式的內存,因此當應用程式超過限制時,部署服務將首先減慢應用程式的速度,然後如果繼續運行,服務將關閉它。我們使用傳統的Spring 框架,甚至沒有Spring Boot,我們嘗試使用不同的庫,但差異很小且毫無價值,這就是創建一個輕量級Spring 替代方案,專注於盡可能減少內存消耗的想法的開始。 .
當我開始設計這個函式庫時,我腦中只有兩個目標:
1 - 盡可能減少記憶體消耗
2 - 從學習的角度以及過渡本身的複雜性來看,盡可能嘗試使用現有的 Java EE API,以使向庫的過渡變得容易。
憑藉這兩個目標,我成功地將其中一個應用程式的記憶體佔用量減少了 40% 左右,並使過渡變得輕鬆快速,因為它與現有解決方案類似。
這裡是 GitHub 儲存庫,您可以在閱讀時檢查程式碼。
整個函式庫有很多部分(截圖如下),大部分實作在主模組中,主模組也分為三種獨立模組:Core、JPA、Web。 App 模組主要用於集成,Plugin 模組是一個 Maven 插件,可協助在套件存檔中建立必要的文件,以使程式庫正常工作
所以我們將從核心模組開始,顧名思義,它包含庫的核心功能,即依賴注入或控制反轉。
為了實現這種功能,首先它首先在編譯階段掃描應用程式的類路徑,以查找庫應管理的所有註釋的類,以便為帶註釋的類建立元件定義。
組件定義基本上包含了我們稍後從該類實例化對象所需的所有信息,例如構造函數信息,如果有一些具有註入註釋的setter(僅支持構造函數和setter注入)如果該類有一些介面或擴展一些其他類,我們將擁有從此類創建物件所需的所有資訊(下面的螢幕截圖)。
然後,在掃描所有類別路徑註解並建立所需的所有元件定義後,我們將它們儲存為 JSON 檔案作為 JSON 檔案。
核心模組的第二個也是主要功能是基於工廠設計模式的依賴注入和控制反轉,因此我們有ApplicationContext接口,它自身擴展了ComponentFactory 接口,此介面的主要方法是getComponent 方法,該方法將從元件名稱傳回物件。
正如您首先在上面的螢幕截圖中看到的,我們嘗試檢查該元件是否存在於已初始化的Singleton 元件中,如果不存在,那麼我們首先從JSON 檔案中取得元件定義,然後啟動while 循環在將組件定義及其相依性傳遞給組件組裝器之前取得組件的所有依賴項,以取得準備注入的完整物件。
JPA 模組的實作與spring data JPA 非常相似,但非常小,之所以非常相似,是因為我在許多專案中使用了spring data,我發現它很容易使用,正如我之前所說,我想過渡到庫要流暢並且需要盡可能少的工作,因此實現我自己的迷你Spring 資料版本是最好的選擇。
實作圍繞JpaRepository 接口,其中包含最常見的資料庫操作,如保存、刪除和findAll...,為了使用JPA 模組,您需要擴展此接口並提供此接口應管理和管理的實體它是id,那麼在擴充介面並使用Repository 註解進行註解之後,您可以定義方法並使用Query 註解對其進行註解並提供JPQL 查詢,然後程式庫在編譯階段將建立一個實作該介面的功能齊全的類別。
該程式庫還將管理應用程式的事務部分,因此從事務的角度來看,所有儲存庫介面和任何帶有事務註釋的類別都將由庫管理。因此,對於任何事務元件,程式庫將建立代理程式來管理基於 Transactional 註解的事務,並且還將管理實體管理器生命週期。
Web 模型負責管理應用程式的所有Web 部分,根據設計,它是一個獨立的模組,這意味著它可以獨立於庫中的其餘模組使用,像往常一樣,它的用法與某些模組非常相似熟悉的Java EE 函式庫,例如Spring web 或Jax-rs。
實作是基於註解的,你有用Controller 註解註解的類,在這個控制器中你會找到用PathMapping 註解的方法,這些方法將處理特定的路徑或特定的路徑基於某些標準的請求,例如請求類型、內容類型......
從外部看,它與其他庫非常相似,但從內部看,它是不同的,因為該庫將在運行時更改這些Controller 類,以使它們全部擴展 BaseHttpServlet ,它也擴展了HttpServlet 並且它們將作為常規servlet 工作。
正如您在上面的螢幕截圖中所看到的,首先我們在init 方法中初始化元件,以使用WebApplicationContext 注入所有依賴項,然後我們將處理所有請求使用handleRequest 方法來到此控制器,透過這種方法,我們將使用現有的servlet api 來管理控制器,這將有助於保持較低的記憶體佔用量,並減少開銷,因為函式庫充當插件補充servlet API 工作。
首先,我們嘗試將請求映射到正確的方法,然後,我們嘗試通過從上下文或像請求一樣的HttpServletRequest 獲取信息,將所有請求的信息注入方法內參數或標頭或路徑變數或請求內文...
我們轉換所有這些信息,然後在請求時將它們作為參數注入到方法中,然後我們執行該方法並根據PathMapping 生成或內容類型轉換結果或結果(通過默認是application/ Json) 接著我們將內容寫入HttpServletResponse.
最後,如果流程中出現問題並拋出錯誤,我們會捕獲此錯誤或異常,並嘗試根據異常的類型進行處理,我們有異常處理程序來處理不同類型的異常,並且用戶還可以提供更多處理程序來按照他想要的方式處理任何異常。
最後也是重要的部分是 Maven 插件,它將創建應用程式正常工作以及建置 jar 或 war 套件所需的所有檔案。
首先,外掛程式將掃描類別路徑和依賴項以搜尋 component-definitions-json 文件,從該文件中它將產生:
lazy-application.json:包含應用程式的所有元件及其相依性
lazy-application.properties:包含控制器和實體的列表,因此我們不需要在運行時掃描類路徑。
最後,如果包裝是 jar,我們將獲得主類。
最後我們建立套件存檔文件,其中包含應用程式程式碼及其依賴項以及我們在上一步中產生的文件。
我盡量不深入細節,以使文章簡短且不那麼複雜,易於理解,當然,程式碼可以在 GitHub 上找到,這樣你也可以使用它。如果你有問題,請將它們放在下面,我會嘗試回答他們。
以上是為什麼我創建了一個輕量級迷你彈簧替代品以及我是如何做到的的詳細內容。更多資訊請關注PHP中文網其他相關文章!