iT邦幫忙

2024 iThome 鐵人賽

DAY 20
0
Software Development

從零開始構建能理解語義的 Linebot 架構系列 第 20

使用 Spring Boot 開發 Backend Bot Server: 從 IoC 容器到 DI 實踐

  • 分享至 

  • xImage
  •  

使用 Spring Boot 開發 Backend Bot Server

  • 前面說明了訊息前處理的部分,包括如何使用AWS Lambda接收及解析LINE Platform的Webhook,並將訊息及一些必要資訊傳送到訊息佇列(Kafka)中。
  • 而本系列文終於到了進入後續處理的階段,也就是Bot Server開發的介紹。
    由於我們的Bot Server是基於Java的Spring框架來開發,因此本章將首先介紹Spring的核心概念,並透過程式結構來了解一個Spring專案應有的樣貌。

控制反轉 (Inversion of Control, IoC) 與 依賴注入(DI, Dependency Injection)

控制是什麼? 又反轉了什麼?

  • 這邊要先理解的是,Java是一個物件導向的程式語言,所有的邏輯都會經由物件來完成。

  • 為了說明IoC及DI,我們先忘記前面提到的架構。假設我們把分工簡化到極致,全部都在一個程式內完成,那麼主程式流程大概會如下:

  • 1.建立一個監聽事件的物件: eventHandler

    • 設定要監聽的IP、Port、驗證資訊,以及要檢查的格式。
    • 呼叫Function: listen()來監聽事件
  • 2.建立一個剖析事件的物件,從中取出必要資料及使用者訊息: eventProcesser

    • 設定剖析完成後,要輸出的格式,例如一個普通的Java Class,或者一個JSON String。
    • 呼叫Function: process()來處理事件
  • 3.建立一個回應事件的物件,replyHandler

    • 設定要回應的目的端,例如Kafka的Broker IP、Topic,及驗證資訊。
    • 呼叫Function: reply()來回應事件

上面的流程,我們可以更簡化成兩個部分:

  • 1.商業邏輯

    • 監聽事件,處理事件,回應事件
  • 2.控制商業邏輯所需要的依賴

    • 監聽事件時: 建立監聽事件的物件: eventHandler,並且設定好要監聽的IP、Port、驗證資訊,以及要檢查的格式。
    • 處理事件: 建立剖析事件的物件: eventProcesser,並且設定好剖析完成後,要輸出的格式。
    • 回應事件: 建立回應事件的物件: replyHandler,並且設定好要回應的目的端資訊。

控制 (Control)

  • 其中,控制商業邏輯所需要的依賴,就是IoC的控制(Control)。講的就是: 在執行商業邏輯的過程中,設定並且實例化所需要的物件。

控制反轉 (Inversion of Control, IoC)

  • Inversion這個單字翻成反轉可能比較難懂,實際上他的意思比較接近於外包,也就是,把設定並且實例化所需要的物件這項工作,通通外包給一個跟商業邏輯無關的第三方程序。經由IoC化以後的程式流程會包含兩個程序,大概會是這樣:

  • 1.第三方程序

    • 建立一個監聽事件的物件: eventHandler,並且設定好要監聽的IP、Port、驗證資訊,以及要檢查的格式。
    • 建立一個剖析事件的物件: eventProcesser,並且設定好剖析完成後要輸出的格式。
    • 建立一個回應事件的物件: replyHandler,並且設定好要回應的目的端資訊。
  • 2.等第三方程序把所有要用到的物件都做好以後,開始執行商業邏輯的主流程:

    • 監聽事件
      • 從第三方程序拿到eventHandler並執行listen()。
    • 處理事件
      • 從第三方程序拿到eventProcesser並執行process()。
    • 回應事件
      • 從第三方程序拿replyHandler並執行reply()。

IoC的好處

  • 簡潔的主流程

    • 因為我們把設定並且實例化所需要的物件這項工作給外包出去了,所有相關程式碼都不會在主流程看到,而是寫在第三方程序。
    • 這對一些邏輯複雜,或者常需抽換依賴的系統來說相當重要,對於一個不是AI的閱讀者(也就是我們)來說,我們可以專注在理解程式的主流程就是要監聽/處理/回應事件,而不會被中間的控制依賴的程式碼干擾
  • 解掉主流程與依賴的耦合,方便依賴抽換

    • 同樣是因為控制依賴這件事不在主流程內,當我們要抽換依賴的實作時,可以完全不用改變主流程,直接要求第三方抽換需要的依賴即可。
    • 例如,當我們要監聽的事件從Kafka換成Redis或其他來源,又或者是輸出要從JSON換成YAML格式,只需要開發好相關工具,再通知第三方改變依賴,不需要改變主要的商業邏輯
      而因為拆分了依賴和主流程,這樣的架構也有利於進行單元測試。

依賴注入(DI, Dependency Injection)

  • 簡單來說,IoC是一種概念,而DI是實踐IoC的方法之一。
  • DI指的是,透過容器(Container)作為第三方程序,來託管所有需要的依賴實例,並且在需要時,透過類別的建構子(Constructor)、方法(setter Function)、或者屬性(Field),來將實例傳遞給需要的對象。

Spring Framework 及 Spring Boot

  • Spring這個Framework就是使用上述DI的方式,幫我們實現IoC這個概念。

Spring Framework 及 容器

  • Spring Framework提供了容器,來託管並實例化所有需要的物件。

    • 注: 這裡說的容器不是Docker Container
  • 在Spring中:

    • Bean 代表了所有商業邏輯所需要的物件
    • Application Context就是用來管理所有實例的容器,由它負責創建、配置、管理和銷毀應用程序中的 Beans:

https://ithelp.ithome.com.tw/upload/images/20241004/20105227zEUtDOsG5w.png
圖: 在Spring中,容器就是Application context,負責託管Beans

Spring Boot

  • Spring 包含了多個子項目,包含Web開發的Spring Web MVC, 與資料庫對接的Spring Data等等。Spring Boot則是其中一個子項目,他的目的是先幫開發者做好一些繁雜的設定,讓開發者得以更專精於主要商業邏輯的開發。
  • 為了簡化說明,在後續的章節中,我們都用Spring來代稱Spring boot。

Spring Boot提供的好處

  • 配置方式

    • 相較於Spring Framework,Spring Boot會自動將以往需要手動配置的一些細節設定好
    • Spring Framework比較像拼裝車,而Spring Boot的精神,是先給你一個完整能運作(Ready-to-use)的車子,再讓開發者根據需求去修改配置。
  • 使用簡單的Annotation註解,來配置並組合成商業邏輯

  • 簡化執行方式

    • 以一個Web程式來說,Spring Framework需要將程式打包為.WAR文件,並部署到外部應用伺服器(如 Tomcat)。
    • Spring Boot則是內嵌了Tomcat,當你執行main方法時,即可啟動應用,無需額外的伺服器部署。基本上只要設定得當,我們可以直接用java -jar 程式名稱.jar 來執行程式。
  • 提供Starter POM

    • Starter POM是包含了各種用途的依賴集合,例如要和MongoDB溝通,只需要在Maven的pom.xml設定檔加入spring-boot-starter-data-mongodb這個starter,就會包含所有已經選好的依賴,而在Spring Framework則需要自己逐個把依賴加入。
    • 注意: Starter"理論上"包含所有需要的依賴,但還是會有一些狀況需要自己加入。

使用Spring Initializr建立專案

  • 我們可以在官方提供的Spring Initializr網站,根據需求選出需要的依賴starter等,Spring Initializr就會根據我們的設定,將相關依賴和檔案結構,甚至是進入點的程式都打包好。
  • 下載後解壓縮,會得到一個完整的初始專案,就可以在上面方便地進行開發。
    https://ithelp.ithome.com.tw/upload/images/20241004/20105227pWJnvqhov6.png
    圖: 使用Springboot: 用Spring Initializr下載初始專案

一個初始Spring專案結構

https://ithelp.ithome.com.tw/upload/images/20241004/201052275q2c6f06tN.png

  • 上面是我們從Spring Initializr下載的初始專案,可以看到DemoApplication,就是程式進入點。

總結

  • 本章說明了控制反轉 (Inversion of Control, IoC),以及Spring Boot的基本概念。
  • 在介紹Spring Boot的好處時有提到,可以用簡單的Annotation,來配置並組合成商業邏輯。實際上一個Spring的程式是由多個Annotation標示的實例組成的,這部分我們在下一章會介紹本專案所用到的Annotation。

Citation

https://docs.spring.io/spring-framework/reference/core/beans/basics.html
https://spring.io/projects/spring-boot
https://docs.spring.io/spring-boot/reference/using/structuring-your-code.html
https://docs.google.com/document/d/1yt8QwUY-FPECg8WCxzM7KXeg5oRyTjnXAQ-qEM1j07E/edit#heading=h.b89bcmyb8z3n


上一篇
執行環境設定: 背景執行與記憶體監控指令
下一篇
使用 Spring Boot 開發 Backend Bot Server: Bean的組合與 ComponentScan 機制
系列文
從零開始構建能理解語義的 Linebot 架構30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言