# AOP(Aspect-Oriented Programming)
* aim to method/class level-handle(cf. interceptor aim to handle request or respons of webapplication level)
1. aspect class declaration : @Aspect
2. pointcut: the valaildation of the selection rule pattern
3. @after/before/afterthrowing: declare the action
* before advice
* after advice
* around advice
* after-throwing advice
5. jointpoint: working flow at any moment, examine by pointcut rule to check valid or not
https://www.baeldung.com/spring-bean-annotations
```xml=
<!-- spring boot aop 套件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
````
----
1.

return_type package.java_file.method
method *(..)
\* for wildcard method name
\.\. imply exist or not
---
2. AOP @around use annotate to register AOP

all use \@Loggalbe will register the above AOP method.

build @annotation type


--------
## object-oriented programming diagram

1. logClass will be the most connected in relationship diagram, not the business logic one. too many relationships to the crosscutting objects.
2. code is still required in each method.
3. cant be changed all at once.
## AOP diagram

1. create aspect configuration to tell which objects in which method that these aspect should apply to.

## test proxy by innerclass callback/ crossClass callback
1. pure call the function : hit the proxy, aspect trigger once

2. inner class callback :same class method dont touch the proxy=> aspect triggerd once

3. cross class\(also aspect applied\) callback: trigger the aspect twice

4. aspect cant applied private method
5. @afterThrow wont ignite if the method catch the exception

compare with no try Catch

----
spring manage beans\(aspect,restcontroller,service....etc\),
when the request/callback cross the beans, the aspect proxy will be triggered.
=> inner class call as following <font color="red">won't create transaction</font>
```
@Transactional
+--------------+ +--------------+
|AClass.method1| --> |AClass.method2|
+--------------+ +--------------+
```
----
## aspect annotation
before: 綁定傳入目標前資料取得
```java=
@Before("alldelegate()")
public void LoggingAdviceForClass(JoinPoint joinPoint) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 記錄下請求內容
log.info("=== Request Start ===");
log.info("req Url : " + request.getRequestURL()
.toString());
log.info("req Method : " + request.getMethod());
log.info("req IP : " + request.getRemoteAddr());
log.info("req Class : " + joinPoint.getSignature()
.getDeclaringTypeName() + "."
+ joinPoint.getSignature()
.getName());
log.info("req params : " + Arrays.toString(joinPoint.getArgs()));
}
```
afterreturn: 綁定資料處理後<font color="green">讀取</font>資料, 異常則不觸發
```java=
@AfterReturning(pointcut = "alldelegate()", returning = "ret")
public void returning2(Object ret) throws Throwable {
ObjectMapper obj = new ObjectMapper();
log.info(obj.writeValueAsString(ret));
}
```
afterThrow: 綁定資料處理後<font color="green">讀取</font>資料, 異常才觸發
ex.
```java=
@AfterThrowing(pointcut ="alldelegate()",throwing="ex")
public void throwIng(Exception ex) {
System.out.println("aspect: @AfterThrowing(\"alldelegate()\")");
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
log.error(sw.toString());
}
```
pointcut: 定義切入點
ref: [pointcut pattern](https://openhome.cc/Gossip/Spring/Pointcut.html)
public 不指定回傳類型\(*\)
com.monk.AOPdemo.controller\.\.\* 表示com.monk.AOPdemo.controller 或其下之package
\*\(\.\.\) 任意名稱 任意args之方法
```java=
@Pointcut("execution(public * com.monk.AOPdemo.controller..*.*(..)))")
public void alldelegate() {
}
@Pointcut("within(com.monk.AOPdemo.controller..*)")
public void alldelegate() {
}
```
around:自由度大,可handle before/after/trycatch <font color="red">修改</font>資訊
----
```
* get*() 無論回傳類型 方法名稱開頭為get... 無參數
```

考慮以上邏輯, aspect也適用計算request執行時間
```java=
private long startmillsecond;
@Pointcut("execution(public * com.monk.AOPdemo.controller.*.*(..)))")
public void alldelegate() {
}
@Before("alldelegate()")
public void LoggingAdviceForClass(JoinPoint joinPoint) {
this.startmillsecond = System.currentTimeMillis();
}
@AfterReturning(pointcut = "alldelegate()", returning = "ret")
public void returning2(Object ret) throws Throwable {
long endmillsecond = System.currentTimeMillis();
log.info("timeelapse is " + (int)(endmillsecond - this.startmillsecond));
}
```
###### tags: `AOP` `SPRING`