[Start Spring Boot] Spring AOP

·2024년 4월 26일
0

Start Spring Boot!

목록 보기
51/53
post-thumbnail

AOP란?

  • 관점 지향 프로그래밍
  • 공통된 부분을 모듈화 하여 처리하는 개념
  • 로깅, 인코딩, 보안, 에러체크등 공통부분을 분리해서 재사용 하자!

프록시 패턴

  • 스프링 AOP를 사용하는 방법
  • 공통 모듈을 프록시로 만들어서 DI로 연결된 빈 사이에 적용
  • 프록시 객체를 만들어서 대신 처리하는 방식

용어정리

Compile Time

Advice

  • 실행되는 코드, 즉 부가기능을 의미

Pointcut

  • 특정 포인트, AOP를 어느 시점에 적용할 것인가

Aspect

  • Advice + Pointcut
  • 공통 기능을 의미한다

Weaber

  • AOP를 구현한 프레임워크를 말함

Runtime

Join Point

  • 실행되는 인스턴스
  • Pointcut에 정의된 조건이 참이면 호출
  • 메소드 호출과 관련된 정보를 가진다.

사용하기

dependencies

  • build.gradle
dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-aop'
    
}

@Aspect

  • LoggingAspect.java
@Configuration
@Aspect
public class LoggingAspect {

}
  • 다음과 같이 명시해서 AOP를 수행하는 클래스임을 선언한다.

@Pointcut

 @Point("execution(* com.chan.ssb.*.*.*(..))")
  • 다음과 같이 실행할 시점을 설정하는 함수로 많은 설정방법이 있다.

@Before

  • 메소드 호출 이전에 실행한다.
    @Before("execution(* com.chan.ssb.*.*.*(..))")
    public void logMethodCallBefore(JoinPoint joinPoint) {
        logger.info("Before Aspect - {}", joinPoint);
    }
    

@After

  • 메소드 실행 이후 수행할 작업을 지정한다.
  • 메소드의 실패, 성공과 상관없이 실행한다.
    @After("execution(* com.chan.ssb.*.*.*(..))")
    public void logMethodCallAfter(JoinPoint joinPoint) {
        logger.info("After Aspect - {} is called", joinPoint);
    }

@AfterReturning

  • 메소드의 실행에 성공하였을 때, 수행한다.
    @AfterReturning(
            pointcut = "execution(* com.chan.ssb.*.*.*(..))",
            returning = "resultValue"
    )
    public void logMethodCallAfterReturning(JoinPoint joinPoint, Object resultValue) {
        logger.info("AfterReturning Aspect - {} is called {}", joinPoint, resultValue);
    }
    

@AfterThrowing

  • exception 발생시 수행한다.
    @AfterThrowing(
            pointcut = "execution(* com.chan.ssb.*.*.*(..))",
            throwing = "exception"
    )
    public void logMethodCallAfterThrowing(JoinPoint joinPoint, Exception exception) {
        logger.info("AfterThrowing Aspect - {} is called {}", joinPoint, exception);
    }
    

@Around

  • 메소드 실행 이전과 이후에 무엇인가 수행한다
    @Around("execution(* com.chan.ssb.*.*.*(..))")
    public Object logMethodCallAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        logger.info("Around Aspect before - {} is called", proceedingJoinPoint);
        Object returnValue = proceedingJoinPoint.proceed();
        logger.info("Around Aspect after - {} is called", proceedingJoinPoint);

        return returnValue;
    }
    
  • ProceedingJoinPoint을 이용해서 메소드를 실행 시킬 수 있다.

Pointcut 관리하기

  • 지금과 같이 Pointcut을 사용하는 것은 코드의 변경시 오류를 발생하고 좋지 않다.
  • CommonPointcutConfig을 생성해서 관리해보자
  • CommonPointcutConfig.java
package com.chan.ssb.aspect;

import org.aspectj.lang.annotation.Pointcut;

public class CommonPointcutConfig {

    @Pointcut("execution(* com.chan.ssb.player.*.*(..))")
    public void playerPackageConfig() {}

    @Pointcut("execution(* com.chan.ssb.user.*.*(..))")
    public void userPackageConfig() {}

    @Pointcut("execution(* com.chan.ssb.team.*.*(..))")
    public void teamPackageConfig() {}

    @Pointcut("bean(*Service*)")
    public void allPackageConfigUsingBean() {}

    @Pointcut("@annotation(com.chan.ssb.aspect.MyLog)")
    public void myLogAnnotation() {}

}
  • 사용하기
@Before("com.chan.ssb.aspect.CommonPointcutConfig.playerPackageConfig()")
  • 다음과 같이 정의해서 사용할 수 있다.
  • ("bean(Service)"): Service를 포함하는 모든 빈을 선택
  • ("@annotation(com.chan.ssb.aspect.MyLog)"): 사용자가 정의한 어노테이션을 선택한다.

어노테이션 정의 하기

  • MyLog.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLog {
}
  • @Target: 적용될 대상을 지정
  • @Retention: 대상의 메모리를 언제까지 유지할 것인지 결정하는 애노테이션
  • 사용하기
    @MyLog
    @GetMapping("")
    

profile
백엔드 개발자가 꿈인 컴공과

0개의 댓글

관련 채용 정보