Spring Boot AOP
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();
}
}
결과