implementation 'org.springframework.boot:spring-boot-starter-aop'
package com.example.aop.dto;
public class User {
private String id;
private String pw;
private String email;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPw() {
return pw;
}
public void setPw(String pw) {
this.pw = pw;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", pw='" + pw + '\'' +
", email='" + email + '\'' +
'}';
}
}
package com.example.aop.controller;
import com.example.aop.dto.User;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class RestApiConroller {
@GetMapping("/get/{id}")
public void get(@PathVariable Long id, @RequestParam String name) {
System.out.println("get method");
System.out.println("get method : " + id);
System.out.println("get method : " + name);
}
@PostMapping("/post")
public void post(@RequestBody User user) {
System.out.println("post method : " + user);
}
}
package com.example.aop.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect // AOP 등록
@Component // Spring에서 관리하도록 Bean 등록
public class ParameterAop {
// 어느 부분을 적용할 것인지 지정(@Pointcut)
// 룰 지정
// 어디다가 적용(execution) 시킬건지 (com.example.aop.controller. 하위에 있는 모든 메소드들을 aop로 보겠다)
@Pointcut("execution(* com.example.aop.controller..*.*(..))")
private void cut() {}
// 들어가기 전에 argument 확인, 메소드 실행 전 어떤 값이 들어가는지 확인
// 언제 실행을 시킬거냐
// (메소드이름)
// JoinPoint, 들어가는 지점에 대한 정보를 가져옴
@Before("cut()")
public void before(JoinPoint joinPoint) {
// 메소드 이름 출력
MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
Method method = methodSignature.getMethod();
System.out.println(method.getName());
Object[] args = joinPoint.getArgs();
for(Object obj : args) {
System.out.println("type : "+obj.getClass().getSimpleName());
System.out.println("value : "+obj);
}
}
// 들어가고 나서는 어떠한 값이 Return이 되는지 확인인
//(value = "메소드명()", returning = "오브젝트 이름") 파라메터랑 동일한 이름
@AfterReturning(value = "cut()", returning = "obj")
public void afterReturn(JoinPoint joinPoint, Object obj) {
System.out.println("return obj");
System.out.println(obj);
}
}
package com.example.aop.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
// 특정 메소드의 실행 시간 측정
@Aspect
@Component
public class TimerAop {
@Pointcut("execution(* com.example.aop.controller..*.*(..))")
private void cut() {}
@Pointcut("@annotation(com.example.aop.annotation.Timer)")
private void enableTimer() {}
@Around("cut() && enableTimer()")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// proceed() 메소드 실행
// result는 메소드 실행에 대한 결과 값 저장장
Object result = joinPoint.proceed();
stopWatch.stop();
System.out.println("total time : "+stopWatch.getTotalTimeSeconds());
}
}
package com.example.aop.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Timer {
}
package com.example.aop.controller;
import com.example.aop.annotation.Timer;
import com.example.aop.dto.User;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class RestApiConroller {
@GetMapping("/get/{id}")
public String get(@PathVariable Long id, @RequestParam String name) {
return id+" "+name;
}
@PostMapping("/post")
public User post(@RequestBody User user) {
return user;
}
@Timer
@DeleteMapping("/delete")
public void delete() throws InterruptedException {
// db logic
Thread.sleep(1000*2);
}
}
package com.example.aop.aop;
import com.example.aop.dto.User;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.io.UnsupportedEncodingException;
import java.util.Base64;
@Aspect
@Component
public class DecodeAop {
@Pointcut("execution(* com.example.aop.controller..*.*(..))")
private void cut() {}
@Pointcut("@annotation(com.example.aop.annotation.Decode)")
private void enableDecode() {}
// decode
@Before("cut() & enableDecode()")
public void before(JoinPoint joinPoint) throws UnsupportedEncodingException {
Object[] args = joinPoint.getArgs();
for(Object arg : args) {
// 특정 객체에 대한 특정 변수 decode
if(arg instanceof User) {
User user = User.class.cast(arg);
String base64Email = user.getEmail();
String email = new String(Base64.getDecoder().decode(base64Email), "UTF-8");
user.setEmail(email);
}
}
}
// encode
@AfterReturning(value = "cut() & enableDecode()", returning = "returnObj")
public void afterReturn(JoinPoint joinPoint, Object returnObj) {
if(returnObj instanceof User) {
User user = User.class.cast(returnObj);
String base64Email = user.getEmail();
String email = Base64.getEncoder().encodeToString(base64Email.getBytes());
user.setEmail(email);
}
}
}
package com.example.aop.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Decode {
}
package com.example.aop.controller;
import com.example.aop.annotation.Decode;
import com.example.aop.annotation.Timer;
import com.example.aop.dto.User;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class RestApiConroller {
@GetMapping("/get/{id}")
public String get(@PathVariable Long id, @RequestParam String name) {
return id+" "+name;
}
@PostMapping("/post")
public User post(@RequestBody User user) {
return user;
}
@Timer
@DeleteMapping("/delete")
public void delete() throws InterruptedException {
// db logic
Thread.sleep(1000*2);
}
@Decode // 값을 변환
@PutMapping("/put")
public User put(@RequestBody User user) {
System.out.println("put");
System.out.println(user);
return user;
}
}
package com.example.aop;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.Base64;
@SpringBootApplication
public class AopApplication {
public static void main(String[] args) {
SpringApplication.run(AopApplication.class, args);
System.out.println(Base64.getEncoder().encodeToString("steve@gmail.com".getBytes()));
}
}