---
# System prepended metadata

title: Spring boot AOP & DI example
tags: [' DI', spring boot, ' AOP']

---

---
tags: spring boot, AOP, DI
---

# Spring boot AOP & DI example

---

## Aspect-Oriented Programming

將一些有在多個地方使用到的功能或服務，如安全檢查或是紀錄等功能抽取出來，單一撰寫。

![](https://i.imgur.com/r4OD2r7.png =500x)

----

### 常用名詞
* Aspect：設計各個獨立可重用的物件，這些物件稱之。

* Joinpoint：Aspect 在應用程式執行時加入流程的時機。

* Pointcut：定義某個 Aspect 在哪些 Joinpoint 時要應用上。

----

### AOP Example
以我們的專案來舉例，如果要計算每項 Request 的時間要如何寫呢？

![](https://i.imgur.com/57caW1B.png)

----

最直覺的方法就是在每個 function 的頭部跟尾部加上紀錄時間：
![](https://i.imgur.com/hUol63S.png)

缺點是維護不易，且程式變得冗雜。

----

### 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 並且撰寫程式碼如下：
![](https://i.imgur.com/Ap411vG.png)
(funciton 的意思是當如果用到 RestController 所標註的 function 時就會被觸發。)

----

* @Aspect: 註解定義此 class 為切面。
* @Around: 在切入點切入內容，且可以控制何時執行切入點自身內容。(使用 ProceedingJoinPoint 控制程式流程。)
    * @Before
    * @After
    * @AfterReturning
    * ...
* ProceedingJoinPoint: 切入點之物件，呼叫 proceed() 可以繼續執行程式碼。

----

### Result
顯示出各個 RestController 被呼叫到的 function 以及執行時間。
![](https://i.imgur.com/2AXtHgT.png =1000x)


---

## Dependency Injection
* 相依：例如 Hello World 程式，相依在 System、String 等類別。當類別有更動，相依的部分也要跟著更動。
* 如：macbook 相依於其上游廠商 hard drive、RAM...

----

## Injection
* 當物件被建立的時候，由調控系統內所有物件的外界實體，將其所依賴的物件注入給它。
![](https://i.imgur.com/y9arAEH.png)

----

### 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/
