4차산업혁명의 일꾼/Java&Spring웹개발과 서버 컴퓨터

스프링 AOP~!

르무엘 2022. 7. 18. 13:34

AOP는 간단하게 객체의 부가기능 설계라고 보면된다.(OOP 주기능)

 

주기능 사이에 부가기능을 넣어줄수 있다.

AOP는 부가기능으로 어드바이스로

@Around 로 핵심기능 수행전과후에 동작하게 할수 있다.

 

어드바이스의 종류는 하기와 같이 5가지가 있다.

 

 

포인트 컷의 expression language의 형태는 하기와 같다.

 

참고로  Setter, Getter , NoArgsConstructor, Entity

는 어노테이션으로 스프링부트에서 자동생성가능하다 할때

 

ApiUseTime 을 JPA로 DB와 연결하고 

API 사용시간의 시작과 끝시간을 

사용자마다 계속 등록하고 업데이트해주는 기능을 만들수 있다.

 

즉 사용자의 API사용시간~! 

최다 사용시간을 사용하는 부가기능을 만드는데 있어서

@Aspect
@Component
public class UseTimeAop {
    private final ApiUseTimeRepository apiUseTimeRepository;

    public UseTimeAop(ApiUseTimeRepository apiUseTimeRepository) {
        this.apiUseTimeRepository = apiUseTimeRepository;
    }

    @Around("execution(public * com.lms.springcore.controller..*(..))")
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
        // 측정 시작 시간
        long startTime = System.currentTimeMillis();

        try {
            // 핵심기능 수행
            Object output = joinPoint.proceed();
            return output;
        } finally {
            // 측정 종료 시간
            long endTime = System.currentTimeMillis();
            // 수행시간 = 종료 시간 - 시작 시간
            long runTime = endTime - startTime;

            // 로그인 회원이 없는 경우, 수행시간 기록하지 않음
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
            if (auth != null && auth.getPrincipal().getClass() == UserDetailsImpl.class) {
                // 로그인 회원 정보
                UserDetailsImpl userDetails = (UserDetailsImpl) auth.getPrincipal();
                Users loginUser = userDetails.getUser();

                // API 사용시간 및 DB 에 기록
                ApiUseTime apiUseTime = apiUseTimeRepository.findByUser(loginUser)
                        .orElse(null);
                if (apiUseTime == null) {
                    // 로그인 회원의 기록이 없으면
                    apiUseTime = new ApiUseTime(loginUser, runTime);
                } else {
                    // 로그인 회원의 기록이 이미 있으면
                    apiUseTime.addUseTime(runTime);
                }

                System.out.println("[API Use Time] Username: " + loginUser.getUsername() + ", Total Time: " + apiUseTime.getTotalTime() + " ms");
                apiUseTimeRepository.save(apiUseTime);
            }
        }
    }
}

기존의 CRUD API 의 주기능에 

API 사용시간츨 측정하는 부가기능을

 AOP로 만드는 것이다.

 

AOP로 만들면 코드중복이 사라지고

주기능에 영향을 최소로 주면서

만들수 있어서 안정적이고 유지보수에도 편리하다.

 

이런것을 예외처리에도 적용할 수 있다.

@Getter
@Setter
public class RestApiException {
    private String errorMessage;
    private HttpStatus httpStatus;
}
@RestControllerAdvice
public class RestApiExceptionHandler {

    @ExceptionHandler(value = { IllegalArgumentException.class })
    public ResponseEntity<Object> handleApiRequestException(IllegalArgumentException ex) {
        RestApiException restApiException = new RestApiException();
        restApiException.setHttpStatus(HttpStatus.BAD_REQUEST);
        restApiException.setErrorMessage(ex.getMessage());

        return new ResponseEntity(
                restApiException,
                HttpStatus.BAD_REQUEST
        );
    }
}

@RestControllerAdvice = @ControllerAdvice + @ResponseBody

 

[참고 @Transactional - Propagation.REQUIRED_NEW ]

LIST