먼저 springboot 환경셋업이 필요합니다.
환경셋업은 아래 링크 참고 부탁드립니다.
https://vmpo.tistory.com/7?category=730732
springboot로 개발환경을 갖췄다면 본격적으로 AspectJ를 적용해보도록하겠습니다.
특정 메소드 실행 전, 실행 후, exception발생시 등 메소드 전 후의 특정 로직을 수행해야 할 경우
활용할 수 있습니다.
ex) 소스 변경으로 인한 영향도 없이 전체 페이지 진입로그를 저장해야할 경우
순서대로 진행하면 Aspectj를 쉽게 적용가능합니다.
전체 코드는 제일 하단에 추가해두었습니다.
1. AspectJ 라이브러리 환경설정
아래와 같이 build.gradle 파일에 dependencies 영역에
implementation 'org.springframework.boot:spring-boot-starter-aop' 를 추가해줍니다.
*springboot의 경우 위 설정만 하더라도 바로 적용가능합니다.
2. @Aspect 적용 클래스 생성
AspectJ는 신규 클래스에 @Aspect 어노테이션만 적용해주면 쉽게 사용가능합니다.
URL 진입처리를 할 Controller class 1개와 aspectJ를 적용할 class 1개를 각각 아래와 같이 생성하겠습니다.
TestConroller는 localhost:8080/test 를 브라우저에서 입력하면, Hello World를 출력하는 간단한 메소드 하나를 정의해두었습니다.
LogAopHelperCLS 클래스에는 @Aspect 어노테이션과 @Componet 어노테이션을 추가해줍니다.
이제 LogAopHelperCLS 클래스에 http://localhost:8080/test 호출시 로그를 생성할 수 있는 코드를 작성해보겠습니다.
먼저, 코드 작성 전 아래 내용에 대한 이해가 필요합니다.
아래 @어노테이션을 LogAopHelperCLS 클래스 즉, @AspectJ어노테이션에 선언된 클래스의 메소드에 선언해주면,
특정 함수 실행 전후의 특정 처리가 가능합니다.
@Pointcut : aspectJ를 적용할 타겟을 정의해준다. 전체 컨트롤러의 함수대상, 특정 어노테이션을 설정한 함수대상,
특정 메소드 대상 등 개발자가 적용하길 원하는 범위를 정의하는 어노테이션
@Before : aspectJ를 적용할 타겟 메소드가 실행되기 '전' 수행됨
@AfterReturning : aspectJ를 적용할 타겟 메소드가 실행된 '후' 수행됨 (제일 마지막에 수행됨)
@Around : aspectJ를 적용할 타겟 메소드 실행 전 , 후 처리를 모두 할 수 있음
그럼 아래와 같이 단순히 실행 전후에 콘솔 로그만 찍어내는 코드를 작성해보겠습니다.
아래코드에서,
@Pointcut 어노테이션은 GetMapping어노테이션이 선언된 메소드에만 aspectj가 적용되도록 제한하고 있습니다.
그리고, @Before, @AfterReturning, @Around 어노테이션에서는 파라미터로 GeMapping()함수를 선언해
해당 범위에 적용할 수 있도록 환경을 만들어주었습니다.
그럼 이제 아래 클래스만 있으면 springboot에서 @GetMapping 어노테이션이 있는 메소드에 aspectj 적용이 가능합니다.
package com.example.c32.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LogAopHelperCLS {
private static final Logger LOGGER = LoggerFactory.getLogger(LogAopHelperCLS.class);
/**
* @GetMapping 설정된 메소드 또는 클래스 설정
* GetMapping 노테이션이 설정된 특정 클래스/메소드에만 AspectJ가 적용됨.
*/
@Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
public void GetMapping(){ }
/**
* @param joinPoint
*/
@Before("GetMapping()")
public void before(JoinPoint joinPoint) {
LOGGER.info("=====================AspectJ TEST : Before Logging Start=====================");
LOGGER.info("=====================AspectJ TEST : Before Logging End=====================");
}
/**
* @param joinPoint
* @param result
*/
@AfterReturning(pointcut = "GetMapping()", returning = "result")
public void AfterReturning(JoinPoint joinPoint, Object result) {
LOGGER.info("=====================AspectJ TEST : AfterReturning Logging Start=====================");
LOGGER.info("=====================AspectJ TEST : AfterReturning Logging END=====================");
}
/**
*
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("GetMapping()")
public Object Around(ProceedingJoinPoint joinPoint) throws Throwable {
LOGGER.info("=====================AspectJ TEST : Around Logging Start=====================");
try {
Object result = joinPoint.proceed();
LOGGER.info("=====================AspectJ TEST : Around Logging END=====================");
return result;
}catch (Exception e) {
LOGGER.error("=====================AspectJ Around Exception=====================");
LOGGER.error(e.toString());
return null;
}
}
}
서버 빌드후 실행해보겠습니다.
위와 같이 test url입력시 LogAopHelperCLS에서 정의한 Log를 콘솔에서 확인 할 수 있습니다.
@Around시작 -> @before시작,종료 -> @Around종료 -> @AfterReturning시작,종료 순서로 실행되는 것을 확인 할 수 있습니다.
@Around어노테이션의 시작 종료는 Object result = joinPoint.proceed(); 전후로 나뉩니다.
디버깅을 해보면 joinPoint.proceed() 가 실제 타겟 함수 실행 결과를 처리하고 있습니다.
위 로직을 응용하면, 특정 url진입시 로그 삽입, 암호화된 파라미터가 있는 url에 대해 복호화처리를
@aspect가 선언된 클래스에서 처리할 수 있어 효율적인 설계가 가능할 것 같습니다.
'springboot' 카테고리의 다른 글
[springboot]Feign client 사용하기 - REST api 간편 호출 (1) | 2021.09.12 |
---|---|
[스프링 스터디] IoC 컨테이너와 빈 (1) | 2021.04.12 |
[springboot] 스프링부트 ajax 호출 예제 - 공공데이터 api활용 (3) | 2019.10.10 |
[springboot] 공공데이터 API 호출 예제 (5) | 2019.10.06 |
[springboot] 스프링부트 + maven + intellij 처음 셋팅 (0) | 2019.10.06 |
최근댓글