You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@Around 애노테이션의 값인 execution(* hello.aop.order..*(..)) 는 포인트컷이 된다.
@Around 애노테이션의 메서드인 doLog 는 어드바이스(Advice )가 된다.
execution(* hello.aop.order..*(..))는hello.aop.order 패키지와 그 하위 패키지(..` )를 지정하는 AspectJ 포인트컷 표현식이다. 앞으로는 간단히 포인트컷 표현식이라 하겠다. 참고로 표인트컷 표현식은 뒤에서 자세히 설명하겠다.
이제 OrderService , OrderRepository 의 모든 메서드는 AOP 적용의 대상이 된다. 참고로 스프링은 프록시 방식의 AOP를 사용하므로 프록시를 통하는 메서드만 적용 대상이 된다.
참고
스프링 AOP는 AspectJ의 문법을 차용하고, 프록시 방식의 AOP를 제공한다. AspectJ를 직접 사용하는 것이 아니다. 인터페이스 껍데기만 가져가서 쓰는것.= 스프링 AOP를 사용할 때는 @Aspect 애노테이션을 주로 사용하는데, 이 애노테이션도 AspectJ가 제공하는 애노테이션이다.
참고 @Aspect 를 포함한 org.aspectj 패키지 관련 기능은 aspectjweaver.jar 라이브러리가 제공하는 기능이다. 앞서 build.gradle 에 spring-boot-starter-aop 를 포함했는데, 이렇게 하면 스프링의 AOP 관련 기능과 함께 aspectjweaver.jar도 함께 사용할 수 있게 의존 관계에 포함된다.
그런데 스프링에서는 AspectJ가 제공하는 애노테이션이나 관련 인터페이스만 사용하는 것이고, 실제 AspectJ가 제공하는 컴파일, 로드타임 위버 등을 사용하는 것은 아니다. 스프링은 지금까지 우리가 학습한 것 처럼 프록시 방식의 AOP를 사용한다.
@Import(AspectV1.class)
publicclassAopTest {
@aspect는 애스펙트라는 표식이지 컴포넌트 스캔이 되는 것은 아니다. 따라서AspectV1` 를 AOP로 사용하려면 스프링 빈으로 등록해야 한다.
이렇게 Aspect 를 스프링 빈으로 등록하면,
자동 프록시 등록기에서 등록된 Aspect 빈을 분해, Aspect 빌더 같은데서 분해한걸 가지고 포인트컷, 어드바이스 를 만들어 어드바이저를 자동으로 만들어냄.
스프링 빈으로 등록하는 방법은 다음과 같다.
@Bean 을 사용해서 직접 등록
@Component 컴포넌트 스캔을 사용해서 자동 등록
@Import 주로 설정 파일을 추가할 때 사용(@Configuration )
isAopProxy 에서 true 를 반환
로그도 잘 찍힘
스프링 AOP 구현2 - 포인트컷 분리
@Around 에 포인트컷 표현식을 직접 넣을 수 도 있지만, @Pointcut 애노테이션을 사용해서 별도로 분리할 수 도 있다.
AOP 적용 전
클라이언트 -> orderService.orderItem() -> orderRepository.save()
AOP 적용 후
클라이언트 -> [doLog() -> doTransaction() ] -> orderService.orderItem() -> [doLog() ] -> orderRepository.save()
그런데 여기에서 로그를 남기는 순서가 [doLog()doTransaction() ] 순서로 작동한다. 만약 어드바이스가 적용되는 순서를 변경하고 싶으면 어떻게 하면 될까?
예를 들어서 실행 시간을 측정해야 하는데 트랜잭션과 관련된 시간을 제외하고 측정하고 싶다면 [doTransaction()doLog() ] 이렇게 트랜잭션 이후에 로그를 남겨야 할 것이다.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
프로젝트 생성
Dependinces 는 Lombok 만.
Web 으로 하지 않고 Test 에서 할 예정.
build.gradle 에 아래 문구 추가 필요
스프링 데이터 JPA 같은거 쓰면 자동으로 추가되는데 디펜던시에 추가하지 않아서 없음.
예제 프로젝트 만들기
리포지토리, 서비스를 간단하게 만들고, 이들을 사용해보는 테스트를 작성
앞으로 여기에 AOP 를 적용해볼 예정.
스프링 AOP 구현1 - 시작
스프링 AOP를 구현하는 일반적인 방법은 앞서 학습한
@Aspect를 사용하는 방법이다.이번 시간에는
@Aspect를 사용해서 가장 단순한 AOP를 구현해보자.@Around애노테이션의 값인execution(* hello.aop.order..*(..))는 포인트컷이 된다.@Around애노테이션의 메서드인doLog는 어드바이스(Advice)가 된다.는hello.aop.order패키지와 그 하위 패키지(..` )를 지정하는 AspectJ 포인트컷 표현식이다. 앞으로는 간단히 포인트컷 표현식이라 하겠다. 참고로 표인트컷 표현식은 뒤에서 자세히 설명하겠다.OrderService,OrderRepository의 모든 메서드는 AOP 적용의 대상이 된다. 참고로 스프링은 프록시 방식의 AOP를 사용하므로 프록시를 통하는 메서드만 적용 대상이 된다.@aspect
는 애스펙트라는 표식이지 컴포넌트 스캔이 되는 것은 아니다. 따라서AspectV1` 를 AOP로 사용하려면 스프링 빈으로 등록해야 한다.이렇게 Aspect 를 스프링 빈으로 등록하면,
자동 프록시 등록기에서 등록된 Aspect 빈을 분해, Aspect 빌더 같은데서 분해한걸 가지고 포인트컷, 어드바이스 를 만들어 어드바이저를 자동으로 만들어냄.
스프링 빈으로 등록하는 방법은 다음과 같다.
@Bean을 사용해서 직접 등록@Component컴포넌트 스캔을 사용해서 자동 등록@Import주로 설정 파일을 추가할 때 사용(@Configuration)isAopProxy 에서 true 를 반환
로그도 잘 찍힘
스프링 AOP 구현2 - 포인트컷 분리
@Around에 포인트컷 표현식을 직접 넣을 수 도 있지만,@Pointcut애노테이션을 사용해서 별도로 분리할 수 도 있다.이걸 사용해서 돌려보자
결과는 동일.
@pointcut
@Pointcut에 포인트컷 표현식을 사용한다.void여야 한다.allOrder()이다. 이름 그대로 주문과 관련된 모든 기능을 대상으로 하는 포인트컷이다. (의미를 부여할 수 있음)어드바이스에서는 포인트컷을 직접 지정해도 되지만, 포인트컷 시그니처를 사용해도 된다. 여기서는@around("allOrder()")` 를 사용한다.private,public같은 접근 제어자는 내부에서만 사용하면private을 사용해도 되지만, 다른 애스팩트에서 참고하려면public을 사용해야 한다.결과적으로
AspectV1과 같은 기능을 수행한다. 이렇게 분리하면 하나의 포인트컷 표현식을 여러 어드바이스에서 함께 사용할 수 있다. 그리고 뒤에 설명하겠지만 다른 클래스에 있는 외부 어드바이스에서도 포인트컷을 함께 사용할 수 있다.이제 어드바이스를 하나 추가해서 조금 더 복잡한 상황을 만들어보자.
스프링 AOP 구현3 - 어드바이스 추가
이번에는 조금 복잡한 예제를 만들어보자.
앞서 로그를 출력하는 기능에 추가로 트랜잭션을 적용하는 코드도 추가해보자. 여기서는 진짜 트랜잭션을 실행하는 것 은 아니다. 기능이 동작한 것 처럼 로그만 남기겠다.
트랜잭션 기능은 보통 다음과 같이 동작한다.
보통 비즈니스 로직을 시작할때 트랜잭션을 걸고, 끝날때 커밋/롤백 결정
비즈니스 로직은 서비스 계층에 들어감.
allOrder()포인트컷은hello.aop.order패키지와 하위 패키지를 대상으로 한다.allService()포인트컷은 타입 이름 패턴이*Service를 대상으로 하는데 쉽게 이야기해서XxxService처럼Service로 끝나는 것을 대상으로 한다.*Servi*과 같은 패턴도 가능하다.@Around("allOrder() && allService()")&&(AND),||(OR),!(NOT) 3가지 조합이 가능하다.hello.aop.order패키지와 하위 패키지 이면서 타입 이름 패턴이*Service인 것을 대상으로 한다.doTransaction()어드바이스는OrderService에만 적용된다.doLog()어드바이스는OrderService,OrderRepository에 모두 적용된다.포인트컷이 적용된 AOP 결과는 다음과 같다.
orderService:doLog(),doTransaction()어드바이스 적용orderRepository:doLog()어드바이스 적용실행 결과

AOP 적용 전
클라이언트 ->
orderService.orderItem()->orderRepository.save()AOP 적용 후
클라이언트 -> [
doLog()->doTransaction()] ->orderService.orderItem()-> [doLog()] ->orderRepository.save()그런데 여기에서 로그를 남기는 순서가 [
doLog()doTransaction()] 순서로 작동한다. 만약 어드바이스가 적용되는 순서를 변경하고 싶으면 어떻게 하면 될까?예를 들어서 실행 시간을 측정해야 하는데 트랜잭션과 관련된 시간을 제외하고 측정하고 싶다면 [
doTransaction()doLog()] 이렇게 트랜잭션 이후에 로그를 남겨야 할 것이다.이것을 확인하기 전에 먼저 포인트컷을 외부로 빼서 사용하는 방법을 알아보자.
All reactions