OOP를 보완하는 수단으로 흩어진 Aspect를 모듈화 할 수 있는 프로그래밍 기법
Concerns는 여러 클래스들에 걸쳐서 나타나는 비슷한 코드들, Filed 주입들을 말한다..
ex ) Transaction 처리, 성능관련 로깅 등
⇒ 이처럼 공통된 로직, 코드들을 모듈화하여 묶어서 개발할 수 있따.
⇒ 컴파일 시점, 로드타임에 AOP 적용 방법은 주로 Aspect에서 사용
⇒ 런타임 시점에 AOP 적용은 주로 Spring AOP에서 사용한다.
매번 프록시 캘르스를 작성해야 한다.
여러 클래스, 여러 메소드에 적용하려면 객체들과의 관계도가 복잡해진다.
ex )
// interface
public interfaceEventService {
voidcreateEvent();
voidpublishEvent();
voiddeleteEvent();
}
// Proxy
@Primary
@Service
public class ProxySimpleEventService implements EventService{
@Autowired
SimpleEventService simpleEventService;
@Override
public void createEvent() {
long begin = System.currentTimeMillis();
simpleEventService.createEvent();
System.out.println(System.currentTimeMillis()-begin);
}
@Override
public void publishEvent() {
long begin = System.currentTimeMillis();
simpleEventService.publishEvent();
System.out.println(System.currentTimeMillis()-begin);
}
@Override
public void deleteEvent() {
simpleEventService.deleteEvent();
}
}
// Real Subject
@Service
public class SimpleEventService implements EventService{
@Override
public void createEvent() {
long begin = System.currentTimeMillis();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("create an evnet");
// Crosscutting concern : 각 메소드 마다 공통된 모듈
System.out.println(System.currentTimeMillis()-begin);
}
@Override
public void publishEvent() {
long begin = System.currentTimeMillis();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Published an event");
System.out.println(System.currentTimeMillis()-begin);
}
public void deleteEvent(){
System.out.println("Delete event");
}
}
⇒ 그래서 Spring AOP 등장
애노테이션 기반의 스프링 @AOP
사용하기 위해서는 spring-boot-starter-aop 의존성 필요
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
@Aspect
@Component
public class PerfAspect {
// createEvent, publlishEvent 메소드에 적용될 aop 이다.
// @Around에 Pointcut을 정의할 수 있다. 즉 적용시점을 정의할 수 있다.
// @Around("execution(* me.jhjhj..*.EventService.*(..))")
// @Around("bean(simpleEventService)")
@Around("@annotation(PerfLogging)")
public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{
long begin = System.currentTimeMillis();
Object retVal = pjp.proceed();
System.out.println(System.currentTimeMillis() - begin);
return retVal;
}
// 메소드 실행 이전에
@Before("bean(simpleEventService)")
public void hello(){
System.out.println("hello");
}
}
// RetentionPolicy에도 다양한 스코프가 존재,
// RetentionPolicy.CLASS : 이 애노테이션을 class 파일까지만 적용하겠다.
@Documented
@Retention(RetentionPolicy.CLASS)
public @interface PerfLogging {
}
✅ Spring AOP 공식 레퍼런스 : https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop-pointcuts