Spring 2022/04/04 AOP

관점 지향 프로그래밍(aspect-oriented programming, AOP)은 횡단 관심사(cross-cutting concern)의 분리를 허용함으로써 모듈성을 증가시키는 것이 목적인 프로그래밍 패러다임이다. 코드 그 자체를 수정하지 않는 대신 기존의 코드에 추가 동작(어드바이스)을 추가함으로써 수행하며, "함수의 이름이 'set'으로 시작하면 모든 함수 호출을 기록한다"와 같이 어느 코드가 포인트컷(pointcut) 사양을 통해 수정되는지를 따로 지정한다. 이를 통해 기능의 코드 핵심부를 어수선하게 채우지 않고도 비즈니스 로직에 핵심적이지 않은 동작들을 프로그램에 추가할 수 있게 한다. 관점 지향 프로그래밍은 관점 지향 소프트웨어 개발의 토대를 형성한다.


파일명 LogAspect.java

package com.example.aop;

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;

@Component
@Aspect
public class LogAspect {

    Logger logger = LoggerFactory.getLogger(LogAspect.class);
    
    // 공통적인 작업을 구현하기 위한 용도
    // 패키지가 com.example.controller인 컨트롤러는 모두 수행
    @Around("execution(* com.example.controller.*Controller.*(..)) or execution(* com.example.mapper.*Mapper.*(..))")
    public Object printLog(ProceedingJoinPoint joinPoint) throws Throwable{

        // 현재시간 보관
        long start = System.currentTimeMillis();

        // 수행되는 클래스명
        String className = joinPoint.getSignature().getDeclaringTypeName();

        String type = "";
        if(className.contains("Controller") == true){
            type = "Controller => ";
        }
        else if(className.contains("Mapper") == true){
            type = "Mapper => ";
        }
        else if(className.contains("Service") == true){
            type = "Service => ";
        }

        // 끝나는 시간
        long end = System.currentTimeMillis();

        String methodName = joinPoint.getSignature().getName();
        logger.info(type + className +"," + methodName);
        logger.info("execute time : " + (end - start));
        // System.out.println("클래스명 : "+className + " 메소드명 : "+ methodName);
        return joinPoint.proceed();
    }
}

파일명 InterceptorConfig.java

package com.example.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

// 인터셉터 환경설정
// 주소로만 필터 처리
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Autowired
    HandlerInterceptor interceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(interceptor).addPathPatterns("/**").
        excludePathPatterns( // 수행되지 않아야 하는 주소를 설정
            "/member/login/**",
            "/member/logout/**",
            "/shop/cart/**",
            "/item/image/**",
            "/item/subimage/**",
            "/resources/**"
            );               
    }       
}

파일명 HttpInterceptor.java

package com.example.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Component
public class HttpInterceptor implements HandlerInterceptor {

    @Override
    public void postHandle(
                HttpServletRequest request, 
                HttpServletResponse response, 
                Object handler,
            ModelAndView modelAndView) throws Exception {
        
        // 주소정보
        String pathName = request.getServletPath();
        // ?뒤의 뭐리정보
        String queryName = request.getQueryString();
        // 세션객체 가져오기
        HttpSession httpSession = request.getSession();
        
        // 세션에 추가된 내용 출력하기
        httpSession.setAttribute("BACKURL", pathName);    
        if(queryName != null){
            httpSession.setAttribute("BACKURL", pathName + "?" + queryName);
        }        
        
        System.out.println("================ start interceptor ================");
        System.out.println(pathName + "," + queryName);        
        System.out.println("BACKURL : " + httpSession.getAttribute("BACKURL"));
        System.out.println("================ end interceptor ================");
    }    
}

파일명 MemberController.java 일부

@PostMapping(value = "/loginaction")
    public String loginactionPOST(
        @RequestParam(name = "uemail") String em,
        @RequestParam(name = "upw") String pw
    ){
        System.out.println("uemail em : " + em);       
        System.out.println("upw    pw : " + pw);    
        
        MemberDTO member = mMapper.memberLogin(em, pw);
        if(member != null){
            System.out.println(member.toString());
            httpSession.setAttribute("M_EMAIL", member.getUemail());
            httpSession.setAttribute("M_NAME", member.getUname());
            httpSession.setAttribute("M_ROLE", member.getUrole());
            // 로그인 성공
            String url = (String)httpSession.getAttribute("BACKURL");
            return "redirect:" + url;
        }
        // 로그인 실패
        return "redirect:/member/login";
    }

좋은 웹페이지 즐겨찾기