AOP 카테고리의 첫 게시물에서는 너무 예전 버전을 중심으로 작성했었고,
이 게시물의 마지막은 '요즘은 너무 캡슐화, 추상화가 잘 되어있다..' 였는데 ㅋㅋㅋ 이제야 그 방법을 통해! AOP 를 만들어 보았습니다.
이전 게시물 -> https://vvh-avv.tistory.com/7
[개발 방향]
우선, (기본 Spring Framework 세팅이 다 되어있다는 가정하에) 정의한 개발방향은 아래와 같았다.
1. Controller 가 아닌 특정 Method 에 로그를 찍을 것
2. Custom Annotation 을 만들어서 사용이 편리하도록 개발할 것
3. Method 별로 보기 쉽도록 Key 를 전달하여 로그를 찍을 수 있게 할 것
[개발 진행]
1번을 하기 위해 2번인 Custom Annotation 파일을 만들었다.
/**
* Logging Annotation
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoggingAnnotation {
// Method 별 보고 싶은 Key 전달
public String logKey() default "";
}
@Target(ElementType.METHOD) | (1번의) 메소드 단위로 실행할 수 있도록 세팅 |
@Retention(RetentionPolicy.RUNTIME) |
런타임 시 작동할 수 있도록 세팅 |
그 뒤로 로깅서비스를 담당 할 Aspect 파일을 만들었다.
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class LogPrintAspect {
private final HttpServletRequest request;
/**
* 메인 로직을 타기 전에 Request 에서 값을 꺼내와 로그를 찍음
*
* @see LoggingAnnotation
* @param loggingAnnotation - logKey
*/
@Before("@annotation(loggingAnnotation)")
public void beforeLogging (LoggingAnnotation loggingAnnotation) {
// custom log print..
log.info("[logKey] : " + loggingAnnotation.logKey());
log.info("[ip] : " + request.getRemoteAddr());
}
}
@Slf4j | log.info(~~) 찍을거니까 선언 |
@Aspect | Spring 에서 이 파일을 AOP 파일로 인식 할 수 있도록 선언 |
@Component | 해당 파일을 Bean 으로 등록시키기 위해서 선언 |
@RequiredArgsConstructor | AOP에서 HttpServletRequest 를 사용하기 위해서 선언 |
[파일 분석]
1.
뭔가 joinPoint 의 로직 전/후를 굳이 나눠서 할건 아니고, 그냥 로직 전에 "여기 들어왔어~" 하는 로그만 찍을거라서
@PointCut 이나 @Around 나 @After 는 선언안하고 @Before 만 선언했다.
-> PointCut Extention 으로는 Annotation 을 사용했을 때만 타면 되니까 "@annotation(어노테이션 인터페이스 파일명)" 이렇게 함!
2.
그렇다면 Controller 에서 Method 단위로 Annotation 을 쓴다고 했는데, 어떻게 사용하냐!
@GetMapping("/main")
@LoggingAnnotation(logKey = "This is LogKey")
public ModelAndView RealMain() throws Exception{
// main logic
return new ModelAndView()
}
-> 이렇게 사용하면 된다. Controller 에서 Parameter 로 logKey 를 넘겨주는 값은,
Aspect 파일에서 인자로 LoggingAnnotation 을 불러서 .logKey() 로 꺼내면 꺼내와 진다 :)
3.
그리고 들어왔으니 ClientIP 같은거를 AOP 에서 뽑기 위해 HttpServletRequest 가 필요했고,
검색해보니 이렇게 사용하면 된다- 라고 하는데, Spring 버전 3.x(?) 이상이면 그냥 내가 하드코딩처럼 하지 않아도
@Autowired 로 HttpServletRequest 를 선언할 수 있다. (하지만 생성자주입을 권장하니 @RequiredArgsConstructor 를 사용)(ps. AOP 에서 Request 를 사용하기, HttpServletRequest 사용하기 를 검색해도 잘 안됐어서 부제로 뽑을까 했다 ㅋㅋ)
HttpServletRequest request = ((ServletRequestAttributes)(RequestContextHolder.currentRequestAttributes())).getRequest();
-> 이렇게 사용하지 않아도 된다는게 <중요!!> 하다. 내가 아닌 스프링에게 주입을 맡기자 :)
이번 기회에 이론으로만 알고 있던 AOP 개념을 명확히 하는 계기가 되었다.
그리고 Custom Annotation 은 꼭 만들어 보고 싶었는데! 드디어 도전해봤다.
이렇게 한 발자국 더 성장하는 개발자가 되어 뿌듯합니다 ^-^//
[참고 사이트]
1) AOP 전반적인 사용 가이드 : https://www.baeldung.com/spring-aop-annotation
2) AOP 에서 파라미터 전달 방법 : http://blog.naver.com/PostView.nhn?blogId=platinasnow&logNo=220129414824
혹시나 이 게시물에 오타나, 잘못된 정보가 있으면 편하게 댓글부탁드립니다! 감사합니다 :D
'Backend > Spring Framework' 카테고리의 다른 글
@Value vs @ConfigurationProperties 비교 (0) | 2019.07.01 |
---|---|
redirect 로 페이지 이동시 값 전달방법 (0) | 2018.07.25 |
[Java/Spring] 파일 다중업로드 기능 구현 (0) | 2018.05.16 |
컨트롤러에서 쿠키저장이 잘 안될 때 해결하는 방법 (0) | 2018.05.09 |
@RequestParam 과 @ModelAttribute (0) | 2018.05.04 |
댓글