Spring AOP 구현 방법 및 적용 예제

Spring 프레임워크의 핵심 기능 중 하나인 AOP(Aspect-Oriented Programming)는 다음과 같은 기능을 제공합니다:

  • 선언적 트랜잭션 관리
  • 사용자 정의 관점(Aspect) 정의

AOP 주요 개념

  • 횡단 관심사(Cross-cutting Concerns): 여러 모듈에 걸쳐 반복되는 공통 기능으로, 비즈니스 로직과는 분리되어야 하지만 반드시 처리해야 하는 부분입니다. 예: 로깅, 보안, 캐싱, 트랜잭션 등
  • 관점(Aspect): 횡단 관심사를 모듈화한 객체로, 일반적으로 클래스 형태로 구현됩니다.
  • 어드바이스(Advice): 관점에서 실제로 수행할 작업으로, 메서드 단위로 정의됩니다.
  • 타겟(Target): 어드바이스가 적용될 대상 객체입니다.
  • 프록시(Proxy): 타겟 객체에 어드바이스를 적용하여 생성된 객체입니다.
  • 포인트컷(Pointcut): 어드바이스가 적용될 위치를 정의하는 표현식입니다.
  • 조인포인트(Join Point): 포인트컷과 일치하는 실제 실행 지점입니다.

예제 준비 코드

public interface UserRepository {
    void create();
    void modify();
    void remove();
    void find();
}

public class UserRepositoryImpl implements UserRepository {
    public void create() {
        System.out.println("사용자 추가 완료");
    }

    public void modify() {
        System.out.println("사용자 정보 수정");
    }

    public void remove() {
        System.out.println("사용자 삭제 처리");
    }

    public void find() {
        System.out.println("사용자 조회 결과");
    }
}

방법 1: Spring API 인터페이스 활용

Spring에서 제공하는 표준 API를 사용하여 구현합니다.

public class BeforeExecutionLogger implements MethodBeforeAdvice {
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getSimpleName() + " 클래스의 " + method.getName() + " 메서드 시작");
    }
}

public class AfterExecutionLogger implements AfterReturningAdvice {
    public void afterReturning(Object result, Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getSimpleName() + " 클래스의 " + method.getName() + " 메서드 종료. 반환값: " + result);
    }
}
<?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.xsd">

    <bean id="userRepository" class="com.example.repository.UserRepositoryImpl"/>
    <bean id="beforeLogger" class="com.example.logger.BeforeExecutionLogger"/>
    <bean id="afterLogger" class="com.example.logger.AfterExecutionLogger"/>
    
    <aop:config>
        <aop:pointcut id="repositoryMethods" expression="execution(* com.example.repository.UserRepositoryImpl.*(..))"/>
        <aop:advisor advice-ref="beforeLogger" pointcut-ref="repositoryMethods"/>
        <aop:advisor advice-ref="afterLogger" pointcut-ref="repositoryMethods"/>
    </aop:config>
</beans>

방법 2: 사용자 정의 AOP 구현

사용자가 직접 관점을 정의하여 구현합니다.

public class CustomAspectHandler {
    public void preProcess() {
        System.out.println("[사전 처리] ===================");
    }

    public void postProcess() {
        System.out.println("[사후 처리] ===================");
    }
}
<bean id="customAspect" class="com.example.aspect.CustomAspectHandler"/>

<aop:config>
    <aop:aspect id="customAspectHandler" ref="customAspect">
        <aop:pointcut id="targetMethods" expression="execution(* com.example.repository.UserRepositoryImpl.*(..))"/>
        <aop:before method="preProcess" pointcut-ref="targetMethods"/>
        <aop:after method="postProcess" pointcut-ref="targetMethods"/>
    </aop:aspect>
</aop:config>

방법 3: 애노테이션 기반 구현

애노테이션을 사용하여 AOP를 설정합니다. 먼저 자동 프록시 설정이 필요합니다.

<aop:aspectj-autoproxy/>
<bean id="annotatedAspect" class="com.example.aspect.AnnotatedAspectHandler"/>
@Aspect
public class AnnotatedAspectHandler {

    @Before("execution(* com.example.repository.UserRepositoryImpl.*(..))")
    public void logBefore() {
        System.out.println("[애노테이션 방식 - 시작]");
    }

    @After("execution(* com.example.repository.UserRepositoryImpl.*(..))")
    public void logAfter() {
        System.out.println("[애노테이션 방식 - 종료]");
    }
}

참고: execution 표현식

execution 표현식은 포인트컷을 정의할 때 사용되며, 메서드 시그니처를 기반으로 적용 범위를 지정합니다.

태그: Spring AOP java aspectj Dependency Injection

8월 22일 03:57에 게시됨