본문 바로가기
Spring

AOP 포인트 컷 @Pointcut

by windy7271 2024. 2. 4.
728x90
반응형

 

 

AOP 란 관점 지향 프로그래밍 이라고 불린다. 

 

서비스들의 비즈니스 메소드들은 복잡한 코드로 구성되어있다. 이럴때 비핵심적이지만 꼭 필요하면서, 공통화 할 수 있는 부분을 빼서 

따로 관리하는것이다.

Request가 들어오고 Controller 까지의 동작방식은 다음과 같다

 

@Joinpoint 

후보들 이라고 생각하면 된다.

 

나는 게시판 으로 예시를 들어보겠다. Controller에 있는 모든 메서드 들에게 후보군으로 설정하겠다.

방식은 2가지로 나눌 수 있다.

 

1. 어노테이션 방법 : 보통 이방식을 많이 사용한다.

@Pointcut("within(@org.springframework.stereotype.Controller *)")
public void controllerPointcut() {

}

 

Controller * : Controller 밑에 있는 모든 메서드들을 말한다.

 

2. 위치 저장 문법:

@Pointcut("execution(* com.encore.board..controller..*.*(..))")

 

 

이렇게 2가지의 설정을 할 수 있다. 그러고 나서 내부 코드도 2가지의 방법으로 할 수 있는데 두 가지 모두 소개 할 예정이다.

 

 

일단 아래 코드 하기 전에 위에 2개중에 첫 번째 방법을 살려두고 두 번째 방법은 주석처리하였다.

1. @Before, @After 방법

    @Before("controllerPointcut()")
    public void beforService(JoinPoint joinPoint) {
        log.info("Before Controller");
//        메소드가 실행되기 전에 인증, 입력값 검증등을 수행하는 용도로 사용하는 사전단계


//        사용자의 요청값을  출력하기 위해 HttpServletRequest 객체를 꺼내는 로직
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest req = servletRequestAttributes.getRequest();
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode objectNode = new ObjectMapper().createObjectNode();
        objectNode.put("Method Name ", joinPoint.getSignature().getName());
        objectNode.put("CRUD Name", req.getMethod());

        Map<String, String[]> paramMap = req.getParameterMap();

        ObjectNode objectNodeDetail = new ObjectMapper().valueToTree(paramMap);
        objectNode.set("user inputs", objectNodeDetail);

        log.info("user request info " + objectNode);
    }


    @After("controllerPointcut()")
    public void afterController(JoinPoint joinPoint) {
        log.info("afterController");
    }

메소드가 실행되기전에 Before가 실행된다.

만약에 홈페이지에서 로그인 을 클릭을 하면 로그인으로 넘어가기 전에 저 코드가 실행이 돼서

ObjectNode에 넣어둔 정보가 나오고 그런다음 

After가 나온다.

 

2. @Around (주로 사용)

 

//    방식 2. @Around 사용 (가장 빈번하게 사용)
    @Around("controllerPointcut()") 
    public Object controllerLogeer(ProceedingJoinPoint proceedingJoinPoint) {



        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest req = servletRequestAttributes.getRequest();

        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode objectNode = new ObjectMapper().createObjectNode();
        objectNode.put("Method Name ", proceedingJoinPoint.getSignature().getName());
        objectNode.put("CRUD Name", req.getMethod());

        Map<String, String[]> paramMap = req.getParameterMap();

        ObjectNode objectNodeDetail = new ObjectMapper().valueToTree(paramMap);
        objectNode.set("user inputs", objectNodeDetail);

        log.info("user request info " + objectNode);

        try {
//            본래의 컨트롤러 메서드 호출하는 부분
            return proceedingJoinPoint.proceed();
        } catch (Throwable e) {
            log.error(e.getMessage());
            throw new RuntimeException(e);
        }finally {
            log.info("end controller");
        }
    }

 

내부 로직은 똑같지만. After부분을 try로 부르면서 굳이 Before, After로 나눌 필요가 없어졌다.

주로 실무에서는 이 코드가 사용된다고 한다. 

반응형

댓글