AOP란?

AOP는 Aspect Oriented Programming 즉, 관점 지향 프로그래밍의 약어이다. 여러 클래스에 나눠져 있는 책임을 Aspect 로 캡슐화하는 접근 방식이다. AOP는 로깅, 트랜잭션, 보안, 인증, 캐싱 공통적인 로직이 요구된다. 이러한 공통의 로직을 횡단 관심사(cross-cutting concern) 라고 부른다. 공통 로직을 애플리케이션, 비즈니스, 데이터 계층에서 구현하게 되면 코드 유지관리가 어렵게 된다. 

AOP 주요 용어

  • Aspect: 흩어진 관심사를 모듈화 하는 것, 부가기능을 모듈화 한다. 
  • Target: Aspect를 적용되는 곳
  • Advice: 실질적으로 어떤 일을 해야하는지 적어놓은것, 부가기능을 담은 구현체다.
  • JointPoint: Advice가 적용될 위치
  • PointCut: JointPoint의 스펙을 정의한 것

스프링 AOP 특징

  • 프록시 패턴 기반의 AOP 구현체이다.
  • 스프링 빈에만 AOP를 적용할 수 있다는 특징이 있습니다. 

스프링 AOP

Spring 에서 다음과 같이 의존성을 추가한다. 

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Aspect 나타내는 클래스를 명시하고 스프링 빈으로 등록한다. @Around 어노테이션 Target 메소드를 감싸서 특정 Advice 실행한다. 시간을 측정하기 위한 로직을 공통으로 뺐다. 

PerfAspect

execution(* com.studyaop.EventService.*(..)) 는 com.studyaop 아래의 패키지 경로의 EventService 객체에 모든 메소드에 Aspect 적용한다. 

@Component
@Aspect
public class PerfAspect {

    @Around("execution(* com.studyaop.EventService.*(..))")
    public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{
        long begin = System.currentTimeMillis();
        Object retVal = pjp.proceed(); // 메서드 호출 자체를 감쌈
        System.out.println(System.currentTimeMillis() - begin);
        return retVal;
    }
}

EventService

public interface EventService {
    void createEvent();

    void publishEvent();

    void deleteEvent();
}

SimpleEventService 

@Component
public class SimpleEventService implements EventService {

    @PerLogging
    @Override
    public void createEvent() {
        try {
            Thread.sleep(1000);
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Created an event");
    }

    @Override
    public void publishEvent() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e){
            e.printStackTrace();;
        }
        System.out.println("Published an event");
    }

    @PerLogging
    @Override
    public void deleteEvent() {
        System.out.println("Delete an event");
    }
}

AppRunner

@Service
public class AppRunner implements ApplicationRunner {

    @Autowired
    EventService eventService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        eventService.createEvent();
        eventService.publishEvent();
        eventService.deleteEvent();
    }
}

 

결과

 

코드

 

참고