# Spring boot AOP & DI example
---
## Aspect-Oriented Programming
將一些有在多個地方使用到的功能或服務,如安全檢查或是紀錄等功能抽取出來,單一撰寫。

----
### 常用名詞
* Aspect:設計各個獨立可重用的物件,這些物件稱之。
* Joinpoint:Aspect 在應用程式執行時加入流程的時機。
* Pointcut:定義某個 Aspect 在哪些 Joinpoint 時要應用上。
----
### AOP Example
以我們的專案來舉例,如果要計算每項 Request 的時間要如何寫呢?

----
最直覺的方法就是在每個 function 的頭部跟尾部加上紀錄時間:

缺點是維護不易,且程式變得冗雜。
----
### Forget it, try AOP
使用 AOP 前要在 pom.xml 設置 dependency
```htmlmixed=
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
```
----
### Log Execution time
再來開新的 class 並且撰寫程式碼如下:

(funciton 的意思是當如果用到 RestController 所標註的 function 時就會被觸發。)
----
* @Aspect: 註解定義此 class 為切面。
* @Around: 在切入點切入內容,且可以控制何時執行切入點自身內容。(使用 ProceedingJoinPoint 控制程式流程。)
* @Before
* @After
* @AfterReturning
* ...
* ProceedingJoinPoint: 切入點之物件,呼叫 proceed() 可以繼續執行程式碼。
----
### Result
顯示出各個 RestController 被呼叫到的 function 以及執行時間。

---
## Dependency Injection
* 相依:例如 Hello World 程式,相依在 System、String 等類別。當類別有更動,相依的部分也要跟著更動。
* 如:macbook 相依於其上游廠商 hard drive、RAM...
----
## Injection
* 當物件被建立的時候,由調控系統內所有物件的外界實體,將其所依賴的物件注入給它。

----
### Why?
* 讓程式達到 loosely coupled。
* 測試容易,物件與物件間可分別測試: [mock object](https://zh.wikipedia.org/wiki/%E6%A8%A1%E6%8B%9F%E5%AF%B9%E8%B1%A1)。
* 維護更新也會較為方便。
----
### How?
聲明 Bean (以下四種為較常用註解)
當 spring 看到註解會自動將其註冊為 bean。
* @Component:可以作用在任何地方,通常把 pojo 實例化到 spring 容器。
* @Service:業務邏輯使用,更詳細紀錄執行方法的地方。
* @Repository:DAO 層使用
* @Controller:它把用戶請求的數據經過業務處理層處理之後封裝成一個Model ,然後再把該Model返回給對應的View進行展示
注入Bean
* @Autowired:Spring 會抓取已存在的 bean,並且在外 new 出新物件,自動注入。
----
### Example
以專案的片段程式碼為例,[UserController](https://github.com/mrwenwei/ESUN-Summer-Project/blob/f5da9516e5f4406346ec6f1240ec7f6ca4291b96/esp-back-end/src/main/java/com/esun/espbackend/controller/UserController.java#L19) 使用到 AutoWierd 自動注入 bean 物件 [UserService](https://github.com/mrwenwei/ESUN-Summer-Project/blob/f5da9516e5f4406346ec6f1240ec7f6ca4291b96/esp-back-end/src/main/java/com/esun/espbackend/service/UserService.java#L15) 如此就能直接使用。
```java=
@RestController
public class UserController {
@Autowired
UserService userService;
@RequestMapping(value = "/GET/users")
public List<UserEntity> getAll() {
return userService.getAll();
}
}
```
UserService 則使用到 [UserRepository](https://github.com/mrwenwei/ESUN-Summer-Project/blob/master/esp-back-end/src/main/java/com/esun/espbackend/repository/UserRepository.java) 的 bean。
```java=
@Service
public class UserService {
@Autowired
UserRepository userRepo;
public List<UserEntity> getAll() {
return (List<UserEntity>) userRepo.findAll();
}
}
```
---
## Reference
https://openhome.cc/Gossip/Spring/
{"metaMigratedAt":"2023-06-14T23:34:35.877Z","metaMigratedFrom":"YAML","title":"Spring boot AOP & DI example","breaks":true,"contributors":"[{\"id\":\"0ee7ad64-ac2e-4bf1-969d-547d09882099\",\"add\":3948,\"del\":982}]"}