[Spring] AOP 구현 (AspectJ 사용)

sua_ahn·2023년 2월 27일
0

Spring

목록 보기
3/8
post-thumbnail

AOP 관점 지향 프로그래밍

(Aspect Oriented Programming)
: 로깅, 보안 같은 공통 기능을 분리하여 관리할 수 있도록 만든 프로그래밍 패러다임

→ model과 controller의 감시자

 

AOP의 목적

: 부가 기능 코드를 핵심 비즈니스 로직의 코드와 분리하여,
코드의 간결성을 높이고 변경에 유연하고 확장이 가능하도록 하는 것

 

AOP 용어

  • Aspect
    : 흩어진 관심사(공통 기능)를 모듈화한 것

  • Target
    : Aspect를 적용하는 곳, 대상 객체 (Advised Object)
    → model과 controller 클래스, 메서드 등

  • Advice
    : Aspect의 동작을 적은 것 (동작 코드)

  • Join Point
    : AOP가 실행되는 시점 (Advice가 적용되는 시점)

 

⇒ logging, 로그인 여부 확인 기능을 구현해보자.

 

 


1. 의존성 추가

pom.xml

  1. AOP 관련 라이브러리 추가
<!-- spring Aop -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.3.25</version>
</dependency>

<!-- 런타임에 동적으로 자바 클래스의 프록시(대리인)를 생성해주는 기능을 제공 -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

<!-- aspectj -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.4</version>
</dependency>
  1. 로깅 및 기본 라이브러리 추가
    >> Spring MVC + Maven project 생성 및 실행1

 

2. xml 설정

aop-context.xml

  1. @Aspect 사용 설정
  2. AopProc 클래스의 객체로 myAop를 생성
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
        
	<!-- aspect annotation 사용 설정 -->
	<aop:aspectj-autoproxy/>
	
	<!-- aop 객체 생성 -->
	<bean id="myAop" class="com.mypack.sample.aop.AopProc"/>
</beans>

web.xml

: <param-value> 태그 내에 위의 설정파일 등록

<servlet>
  <servlet-name>dispatcherServlet</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>
          /WEB-INF/spring/servlet-context.xml
          /WEB-INF/spring/aop-context.xml
      </param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>

 

3. Aspect 클래스 생성

AopProc class

  1. @Aspect 어노테이션을 사용하여 Aspect 클래스 선언

  2. Advice 작성을 위한 어노테이션 @Around로 메소드 실행 시점을 기준으로 로직 구현
    → 파라미터 ProceedingJoinPoint로 타겟 메소드 실행 제어 가능

    ⇒ 로그인 여부 확인 기능과 로깅 기능의 로직 구현

package com.mypack.sample.aop;

import java.util.Date;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AopProc {
	
    // 해당 클라이언트 호출 가로채기
	@Around("within(com.mypack.sample.controller.*) or within(com.mypack.sample.dao.*.*)")
	public Object loggerAop(ProceedingJoinPoint joinpoint) throws Throwable {
		
        // session check
        HttpServletRequest req = ((ServletRequestAttributes)RequestContextHolder
        						.currentRequestAttributes()).getRequest();
            
        if(req != null) {
        	// 세션에 저장돼있는 로그인 객체 얻기
        	HttpSession session = req.getSession();
            MemberDto login = session.getAttribute("login");
            
            id(login == null) {		// 로그인 객체가 없으면 컨트롤러로 이동
            	return "redirect:/sessionOut.do";
            }
        }
        
		// logger
        // 가로챈 메소드에 대한 정보
		String signatureStr = joinpoint.getSignature().toShortString();
		
		try {
        	// 비즈니스 메소드 실행 후의 결과값
			Object obj = joinpoint.proceed();
            // 로그 출력
			System.out.println("AOP log: " + signatureStr + " 메소드 실행 " + new Date());
            // 메소드 실행 결과값 반환
			return obj;
            
		} finally {
			System.out.println("실행후: " + System.currentTimeMillis());
		}
	}

}

 
→ 서블릿에서 controller로 이동 시, sendRedirect()를 사용하는 대신
"redirect:/login.do" 반환

 

+ controller

: 로그아웃 메시지를 출력하는 message.jsp파일로 이동

@GetMapping(value = "sessionOut.do")
public String sessionOut(Model model) {
	String sessionOut = "logout";
    model.addAttribute("sessionOut", sessionOut);
    return "message";
}

 

 

참고: 자바 AOP의 모든 것(Spring AOP & AspectJ)

profile
해보자구

0개의 댓글