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
어드바이스는 기본적으로 순서를 보장하지 않는다. 순서를 지정하고 싶으면 @Aspect 적용 단위로 org.springframework.core.annotation.@Order 애노테이션을 적용해야 한다. 문제는 이것을 어드바이스 단위가 아니라 클래스 단위로 적용할 수 있다는 점이다.
그래서 지금처럼 하나의 Aspect에 여러 어드바이스가 있으면 순서를 보장받을 수 없다. 따라서 "Aspect를 별도의 클래스로 분리해야 한다."
현재 로그를 남기는 순서가 아마도 [doLog() -> doTransaction()] 이 순서로 남을 것이다.
(참고로 이 순서로 실행되지 않는 분도 있을 수 있다. JVM이나 실행환경에 따라 달라질 수 있다.)
로그를 남기는 순서를 바꾸어서 [doTransaction() -> doLog()] 트랜잭션이 먼저 처리되고 이후에 로그가 남도록 변경해보자.
이 코드의 문제점을 찾을 수 있겠는가? 이 코드는 타켓을 호출하지 않는 문제가 있다.
이 코드를 개발한 의도는 타켓 실행 전에 로그를 출력하는 것이다. 그런데 '@around'는 항상 joinPoint.proceed()를 호출해야 한다. 만약 실수로 호출하지 않으면 타켓이 호출되지 않는 치명적인 버그가 발생한다.
@before는 joinPoint.proceed()를 호출하는 고민을 하지 않아도 된다. @around가 가장 넓은 기능을 제공하는 것은 맞지만, 실수할 가능성이 있다.
반면에 @before, @after같은 어드바이스는 기능은 적지만 실수할 가능성이 낮고, 코드도 단순하다.
그리고 가장 중요한 점이 있는데, 바로 이 코드를 작성한 의도가 명확하게 드러난다는 점이다. @before 애노테이션을 보는 순간 타겟실행전에 한정해서 어떤 일을 하는 코드구나 라는 것이 드러난다.
좋은 설계는 제약이 있는 것이다
좋은 설계는 제약이 있는 것이다. @around만 있으면 되는데 왜 제약을 두는가? 제약은 실수를 미연에 방지한다.
일종의 가이드 역할을 한다. 만약 @around를 사용했는데 중간에 다른 개발자가 해당 코드를 수정해서 호출하지 않았다면?
큰 장애가 발생했을 것이다. 처음부터 @before를 사용했다면 이런 문제 자체가 발생하지 않는다.
제약 덕분에 역할이 명확해진다. 다른 개발자도 이 코드를 보고 고민해야 하는 범위가 줄어들고 코드의 의도도 파악하기
쉽다
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.
스프링 AOP 구현4 - 포인트 컷 참조
다음과 같이 포인트컷을 공용으로 사용하기 위해 별도의 외부 클래스에 모아두어도 된다. 참고로 외부에서 호출할때는 포인트컷의 접근 제어자를 'public'으로 열어두어야 한다.
pointcut
AspectV4Pointcut
사용하는 방법은 패키지명을 포함한 클래스 이름과 포인트컷 시그니처를 모두 지정하면 된다.
포인트컷을 여러 어드바이스에서 함께 사용할 때 이 방법을 사용하면 효과적이다.
AopTest : 수정
AspectV4Pointcut.class를 실행하기 위해서 다음 처리를 하자.@Import(AspectV3.class): 주석처리@Import(AspectV4Pointcut.clasS): 추가실행 결과는 같다.
스프링 AOP 구현 5 - 어드바이스 순서
어드바이스는 기본적으로 순서를 보장하지 않는다. 순서를 지정하고 싶으면
@Aspect적용 단위로org.springframework.core.annotation.@Order애노테이션을 적용해야 한다. 문제는 이것을 어드바이스 단위가 아니라 클래스 단위로 적용할 수 있다는 점이다.그래서 지금처럼 하나의 Aspect에 여러 어드바이스가 있으면 순서를 보장받을 수 없다. 따라서 "Aspect를 별도의 클래스로 분리해야 한다."
현재 로그를 남기는 순서가 아마도 [
doLog() -> doTransaction()] 이 순서로 남을 것이다.(참고로 이 순서로 실행되지 않는 분도 있을 수 있다. JVM이나 실행환경에 따라 달라질 수 있다.)
로그를 남기는 순서를 바꾸어서 [
doTransaction() -> doLog()] 트랜잭션이 먼저 처리되고 이후에 로그가 남도록 변경해보자.AspectV5Order
AopTest
@Import({AspectV5Order.LogAspect.class, AspectV5Order.TxAspect.class})부분 추가실행
트랜잭션 어드바이스가 먼저 실행된다.


스프링 AOP 구현6 - 어드바이스 종류
어드바이스는 앞서 살펴본
@Around외에도 여러가지 종류가 있다.어드바이스 종류
@Around: 메서드 호출 전후에 수행, 가장 강력한 어드바이스, 조인 포인트 실행 여부 선택, 반환 값 변환, 예외 변환 등이 가능@Before: 조인 포인트 실행 이전에 실행@After Returning: 조인 포인트가 정상 완료 후 실행@After Throwing: 메서드가 예외를 던지는 경우 실행@After: 조인 포인트가 정상 또는 예외에 관계없이 실행(finally)예제를 만들면서 학습해보자.
참고 정보 획득
모든 어드바이스는
org.aspectj.lang.JoinPoint를 첫번째 파라미터에 사용할 수 있다.(생략해도 된다.)단 @around는 ProceedingJoinPoint를 사용해야 한다.
참고로 ProceedingJoinPoint 는
org.aspectj.lang.joinPoint의 하위 타입이다.JoinPoint 인터페이스의 주요 기능
getArgs(): 메서드 인수를 반환한다.getThis(): 프록시 객체를 반환한다.getTarget(): 대상 객체를 반환한다.getSignature(): 조언되는 메서드에 대한 설명을 반환한다.toString(): 조언되는 방법에 대한 유용한 설명을 인쇄한다.ProceedingJoinPoint 인터페이스의 주요 기능
추가로 호출시 전달한 매개변수를 파라미터를 통해서도 전달 받을 수 있는데 이 부분은 뒤에서 설명한다.
어드바이스 종류
@before
조인 포인트 실행 전
@AfterReturning
메서드 실행이 정상적으로 반환될 때 실행
@AfterThrowing
메서드 실행이 예외를 던져서 종료될때 실행
@after
@around
catchfinally 모두 들어가는 구문 처리 가능AopTest - 변경
실행
순서
@around 외에 다른 어드바이스가 존재하는 이유
@around하나만 있어도 모든 기능을 수행할 수 있다. 그런데 다른 어드바이스들이 존재하는 이유는 무엇일까?
이 코드의 문제점을 찾을 수 있겠는가? 이 코드는 타켓을 호출하지 않는 문제가 있다.
이 코드를 개발한 의도는 타켓 실행 전에 로그를 출력하는 것이다. 그런데 '@around'는 항상
joinPoint.proceed()를 호출해야 한다. 만약 실수로 호출하지 않으면 타켓이 호출되지 않는 치명적인 버그가 발생한다.@before는 joinPoint.proceed()를 호출하는 고민을 하지 않아도 된다.
@around가 가장 넓은 기능을 제공하는 것은 맞지만, 실수할 가능성이 있다.
반면에 @before, @after같은 어드바이스는 기능은 적지만 실수할 가능성이 낮고, 코드도 단순하다.
그리고 가장 중요한 점이 있는데, 바로 이 코드를 작성한 의도가 명확하게 드러난다는 점이다.
@before 애노테이션을 보는 순간 타겟실행전에 한정해서 어떤 일을 하는 코드구나 라는 것이 드러난다.
좋은 설계는 제약이 있는 것이다
좋은 설계는 제약이 있는 것이다.
@around만 있으면 되는데 왜 제약을 두는가? 제약은 실수를 미연에 방지한다.
일종의 가이드 역할을 한다. 만약 @around를 사용했는데 중간에 다른 개발자가 해당 코드를 수정해서 호출하지 않았다면?
큰 장애가 발생했을 것이다. 처음부터 @before를 사용했다면 이런 문제 자체가 발생하지 않는다.
제약 덕분에 역할이 명확해진다. 다른 개발자도 이 코드를 보고 고민해야 하는 범위가 줄어들고 코드의 의도도 파악하기
쉽다
All reactions