Spring

[Spring] AOP

yn98 2024. 11. 10. 23:55

AOP?

AOP는 Aspect-Oriented Programming으로, 관점지향 프로그래밍이라고 부른다.

AOP는 비즈니스 로직과는 별개의 공통 기능(횡단 관심사, cross-cutting concerns)을 분리하여 코드의 중복을 줄이고, 모듈화를 통해 코드의 유지보수를 용이하게 하는 프로그래밍 기법을 말한다.

AOP의 주요 개념

Aspect (관점)

한 문장으로 정리하면 여러 클래스에 걸쳐 있는 관심사의 모듈화이다.

트랜잭션 관리가  Java에서 횡단 관심사의 좋은 예이다.

Spring AOP에서 Aspect는  스키마 기반 접근 방식  또는  @Aspect를 사용하여 구현된다.

 

사용 예시

@Slf4j
@Aspect
@Component
@Order(1) // @커스텀 여러개 쓸 경우 진행 순서
public class LoginAspect {
// ...
}

Joinpoint

한 문장으로 정리하면프로그램 실행 중의 한 지점, 예를 들어 메서드 실행이나 예외 처리를 말한다.

Spring AOP에서 조인 포인트는 항상 메서드 실행을 나타낸다.

 

사용 예시

@Before("PointcutCommon.beforePointcut()") // 전 실행
    public void printLogBefore(JoinPoint jp) {
        String methodName = jp.getSignature().getName(); // 메서드명
        log.info("공통 관심 - 로그 : [{}] 비즈니스 메서드 수행 전 호출",methodName);
    }

 

Advice

특정 Joinpoint 에서 Aspect가 수행하는 액션을 의미한다.

Advice의 다른 유형으로는 "around", "before", "after"  어드바이스가 있다.

사용 예시

@Service
@Aspect
@Slf4j
public class LogAdvice {

    @Before("PointcutCommon.daoLogPointcut()") // 전 실행
    public void printLogBefore(JoinPoint jp) {
        String methodName = jp.getSignature().getName(); // 메서드명
        log.info("공통 관심 - 로그 : [{}] 비즈니스 메서드 수행 전 호출",methodName);
    }
    @AfterReturning("PointcutCommon.daoLogPointcut()") // 성공 실행
    public void printLogAfterReturning(JoinPoint jp) {
        String methodName = jp.getSignature().getName(); // 메서드명
        log.info("공통 관심 - 로그 : [{}] 비즈니스 메서드 수행 성공",methodName);
    }
    @AfterThrowing("PointcutCommon.daoLogPointcut()") // 오류 시 실행
    public void printLogAfterThrowing(JoinPoint jp) {
        String methodName = jp.getSignature().getName(); // 메서드명
        log.info("공통 관심 - 로그 : [{}] 비즈니스 메서드 수행 실패",methodName);
    }
}

Pointcut

어떤 Joinpoint에서 Advice를 실행할지 결정하는 표현식을 의미한다.

execution, @annotation 등의 표현식을 사용하여 메서드 실행 위치를 지정한다.

사용 예시

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class PointcutCommon {

    @Pointcut("execution(* com.coma.app.biz..*DAO.*(..))")
    public void daoLogPointcut() {} // 참조 메서드, 실질적인 기능이 있지않다

}