커스텀 어노테이션과 AOP를 활용한 실행 시간 로깅 관점 구현
전체 구조
src/main/java/
└── com/
└── jiwoo/
└── gdg_spring_week04/
├── GdgSpringWeek04Application.java
├── config/
│ └── AppConfig.java
├── aspect/
│ └── LogExecutionTimeAspect.java
│ └── LogExecutionTime.java
├── controller/
│ └── Controller.java
└── service/
└── SampleClass.java
config
패키지
└──AppConfig.java
package com.jiwoo.gdg_spring_week04.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
}
aspect
패키지
└──LogExecutionTimeAspect.java
package com.jiwoo.gdg_spring_week04.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LogExecutionTimeAspect {
private static final Logger logger = LoggerFactory.getLogger(LogExecutionTimeAspect.class);
// @Around("@annotation(com.jiwoo.gdg_spring_week04.aspect.LogExecutionTime)")
@Around("@annotation(LogExecutionTime)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object proceed = joinPoint.proceed();
long executionTime = System.currentTimeMillis() - start;
logger.info("{} executed in {}ms", joinPoint.getSignature(), executionTime);
return proceed;
}
}
└──LogExecutionTime.java
- 커스텀 인터페이스 클래스
package com.jiwoo.gdg_spring_week04.aspect;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {
}
controller
패키지
└──Controller.java
package com.jiwoo.gdg_spring_week04.controller;
import com.jiwoo.gdg_spring_week04.service.SampleClass;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/sample")
public class Controller {
@Autowired
private SampleClass sampleClass;
@GetMapping("/serve")
public String serve() throws InterruptedException{
sampleClass.serve();
return "Service excuted";
}
}
service
패키지
└──SampleClass.java
package com.jiwoo.gdg_spring_week04.service;
import com.jiwoo.gdg_spring_week04.aspect.LogExecutionTime;
import org.springframework.stereotype.Component;
@Component
public class SampleClass {
@LogExecutionTime
public void serve() throws InterruptedException{
Thread.sleep(2000);
}
}
http://localhost:8080/sample/serve
❌ 커스텀 어노테이션과 Aspect가 다른 패키지에 있을 때 로그 안뜸
→ 다른 패키지에 있을 때는 경로 생략 불가. 경로를 다음과 같이 지정해줘야됨.
@Around("@annotation(com.jiwoo.gdg_spring_week04.aspect.LogExecutionTime)")
⇒ 같은 패키지로 이동해서 실행
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.3.4)
2024-10-09T15:41:49.007+09:00 INFO 18572 --- [gdg-spring-week04] [ main] c.j.g.GdgSpringWeek04Application : Starting GdgSpringWeek04Application using Java 21.0.4 with PID 18572 (C:\Users\cse\OneDrive\문서\workspace\spring\gdg-spring-week04\gdg-spring-week04\out\production\classes started by cse in C:\Users\cse\OneDrive\문서\workspace\spring\gdg-spring-week04)
2024-10-09T15:41:49.013+09:00 INFO 18572 --- [gdg-spring-week04] [ main] c.j.g.GdgSpringWeek04Application : No active profile set, falling back to 1 default profile: "default"
2024-10-09T15:41:51.005+09:00 INFO 18572 --- [gdg-spring-week04] [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
2024-10-09T15:41:51.027+09:00 INFO 18572 --- [gdg-spring-week04] [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2024-10-09T15:41:51.027+09:00 INFO 18572 --- [gdg-spring-week04] [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.30]
2024-10-09T15:41:51.117+09:00 INFO 18572 --- [gdg-spring-week04] [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-10-09T15:41:51.118+09:00 INFO 18572 --- [gdg-spring-week04] [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2004 ms
2024-10-09T15:41:51.936+09:00 INFO 18572 --- [gdg-spring-week04] [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'
2024-10-09T15:41:51.966+09:00 INFO 18572 --- [gdg-spring-week04] [ main] c.j.g.GdgSpringWeek04Application : Started GdgSpringWeek04Application in 3.76 seconds (process running for 4.39)
2024-10-09T15:41:52.038+09:00 INFO 18572 --- [gdg-spring-week04] [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2024-10-09T15:41:52.039+09:00 INFO 18572 --- [gdg-spring-week04] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2024-10-09T15:41:52.041+09:00 INFO 18572 --- [gdg-spring-week04] [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 2 ms
2024-10-09T15:41:54.101+09:00 INFO 18572 --- [gdg-spring-week04] [nio-8080-exec-1] c.j.g.aspect.LogExecutionTimeAspect : void com.jiwoo.gdg_spring_week04.service.SampleClass.serve() executed in 2014ms