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 애노테이션을 적용해야 한다.
그런데 이게 어드바이스 단위가 아니라 클래스 단위로 적용할 수 있다.
그래서 지금처럼 하나의 애스팩트에 여러 어드바이스가 있으면 순서를 보장받을 수 없다.
따라서 애스팩트를 별도의 클래스로 분리해야한다!
지금 순서는 doLog() 하고 doTransaction() 을 한다.
클래스 내부의 @Around 에 @Order 를 넣어도 마찬가지.
이렇게 메서드에 파라미터 넣지 않아도 잘 동작한다.
조인포인트 사용하기 직전에 간단하게 사용하는 어드바이스
@before
조인 포인트 실행 전 @Around 와 다르게 작업 흐름을 변경할 수는 없다. @Around 는 ProceedingJoinPoint.proceed() 를 호출해야 다음 대상이 호출된다. 만약 호출하지 않으면 다음 대상이 호출되지 않는다.
반면에 @Before 는 ProceedingJoinPoint.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으로 열어두어야 한다.이를 사용할때 패키지를 전부 적어야한다.
테스트 해보면 아래와같이 잘 실행된다

스프링 AOP 구현5 - 어드바이스 순서
어드바이스는 기본적으로 순서를 보장하지 않는다. 순서를 지정하고 싶으면
@Aspect적용 단위로org.springframework.core.annotation.Order애노테이션을 적용해야 한다.그런데 이게 어드바이스 단위가 아니라 클래스 단위로 적용할 수 있다.
그래서 지금처럼 하나의 애스팩트에 여러 어드바이스가 있으면 순서를 보장받을 수 없다.
따라서 애스팩트를 별도의 클래스로 분리해야한다!
지금 순서는 doLog() 하고 doTransaction() 을 한다.
클래스 내부의
@Around에@Order를 넣어도 마찬가지.순서를 보장받으려면 이렇게 해야한다.
이렇게 넣어주고 사용해야한다.
결과를 보면 tx 먼저 하고 log 를 찍는다.
순서를 바꿔보면 결과가 아래와 같다.

@Order에서 숫자가 낮을수록 먼저 실행된다.그림으로 보면 아래와 같다

스프링 AOP 구현6 - 어드바이스 종류
어드바이스는 앞서 살펴본
@Around외에도 여러가지 종류가 있다.어드바이스 종류
@Around: 메서드 호출 전후에 수행, 가장 강력한 어드바이스, 조인 포인트 실행 여부 선택, 반환 값 변환, 예외 변환 등이 가능 (모든걸 할 수 있음)@Before: 조인 포인트 실행 이전에 실행@AfterReturning: 조인 포인트가 정상 완료후 실행@AfterThrowing: 메서드가 예외를 던지는 경우 실행@After: 조인 포인트가 정상 또는 예외에 관계없이 실행(finally)이렇게 만들어서 테스트해보면

로그가 잘찍힌다.
이렇게 메서드에 파라미터 넣지 않아도 잘 동작한다.
조인포인트 사용하기 직전에 간단하게 사용하는 어드바이스
@before
조인 포인트 실행 전
@Around와 다르게 작업 흐름을 변경할 수는 없다.@Around는ProceedingJoinPoint.proceed()를 호출해야 다음 대상이 호출된다. 만약 호출하지 않으면 다음 대상이 호출되지 않는다.반면에
@Before는ProceedingJoinPoint.proceed()자체를 사용하지 않는다. 메서드 종료시 자동으로 다음 타켓이 호출된다. 물론 예외가 발생하면 다음 코드가 호출되지는 않는다.@AfterReturning
메서드 실행이 정상적으로 반환될 때 실행
returning에서 이름을 매칭해서 리턴값을 사용가능. (returning속성에 사용된 이름은 어드바이스 메서드의 매개변수 이름과 일치해야 한다.)returning절에 지정된 타입의 값을 반환하는 메서드만 대상으로 실행한다. (부모 타입을 지정하면 모든 자식타입은 인정된다.) 즉 AOP 거는 메서드의 반환 타입이 호환 가능한 returning 의 타입에 대해서만 실행된다.@Around처럼 리턴값을 바꾸는건 불가능. 참고로 set 으로 조작은 가능@AfterThrowing
메서드 실행이 예외를 던져서 종료될 때 실행
throwing의 이름을 매칭해야함.throwing속성에 사용된 이름은 어드바이스 메서드의 매개변수 이름과 일치해야 한다.throwing절에 지정된 타입과 맞는 예외를 대상으로 실행한다. (부모 타입을 지정하면 모든 자식 타입은 인정된다.)@after
메서드 실행이 종료되면 실행된다. (finally를 생각하면 된다.)
정상 및 예외 반환 조건을 모두 처리한다.
일반적으로 리소스를 해제하는 데 사용한다.
정상 케이스 로그

예외 케이스 로그

@Around만 있으면 될것 같은데? 라고 생각이 들 수 있는데 이것들이 있는 이유가 있음.밑에 설명할 예정.
모든 어드바이스는
org.aspectj.lang.JoinPoint를 첫번째 파라미터에 사용할 수 있다. (생략해도 된다.)단
@Around는ProceedingJoinPoint을 사용해야 한다.참고로
ProceedingJoinPoint는org.aspectj.lang.JoinPoint의 하위 타입이다.ProceedingJoinPoint 인터페이스의 주요 기능
proceed(): 다음 어드바이스나 타켓을 호출한다.JoinPoint 인터페이스의 주요 기능
getArgs(): 메서드 인수를 반환합니다.getThis(): 프록시 객체를 반환합니다.getTarget(): 대상 객체를 반환합니다.getSignature(): 조언되는 메서드에 대한 설명을 반환합니다.toString(): 조언되는 방법에 대한 유용한 설명을 인쇄합니다.추가적으로 메서드 호출할때 사용하는 파라미터를 AOP 에서 파라미터로 받아서 사용할 수 있다.
리턴을 캐치해서 사용하듯이. 방법은 뒤에서 설명할 예정.
@around
joinPoint.proceed() 호출 여부 선택joinPoint.proceed(args[])try ~ catch~ finally모두 들어가는 구문 처리 가능ProceedingJoinPoint를 사용해야 한다.proceed()를 통해 대상을 실행한다.proceed()를 여러번 실행할 수도 있음(재시도)전체 실행 로그
순서
@Aspect안에서 동일한 조인포인트의 우선순위를 정했다.@Around,@Before,@After,@AfterReturning,@AfterThrowing@Aspect안에 동일한 종류의 어드바이스가 2개 있으면 순서가 보장되지 않는다. 이 경우 앞서 배운 것 처럼@Aspect를 분리하고@Order를 적용하자.@around 외에 다른 어드바이스가 존재하는 이유
@Around하나만 있어도 모든 기능을 수행할 수 있다. 그런데 다른 어드바이스들이 존재하는 이유는 무엇일까?다음 코드를 보자.
이 코드의 문제점은 타겟을 호출하지 않았다는 것이다.
이것 빼먹으면 aop 이후에 동작이 작동하지 않는다.
@Around는 항상joinPoint.proceed()를 호출해야 한다. 만약 실수로 호출하지 않으면 타켓이 호출되지 않는 치명적인 버그가 발생한다.@Before는joinPoint.proceed()를 호출하는 고민을 하지 않아도 된다.@Around가 가장 넓은 기능을 제공하는 것은 맞지만, 실수할 가능성이 있다. 반면에@Before,@After같은 어드바이스는 기능은 적지만 실수할 가능성이 낮고, 코드도 단순하다. 그리고 가장 중요한 점이 있는데, 바로 이 코드를 작성한 의도가 명확하게 드러난다는 점이다.@Before라는 애노테이션을 보는 순간 아~ 이 코드는 타켓 실행 전에 한정해서 어떤 일을 하는 코드구나 라는 것이 드러난다.좋은 설계는 제약이 있는 것이다
좋은 설계는 제약이 있는 것이다.
@Around만 있으면 되는데 왜? 이렇게 제약을 두는가? 제약은 실수를 미연에 방지한다. 일종의 가이드 역할을 한다. 만약@Around를 사용했는데, 중간에 다른 개발자가 해당 코드를 수정해서 호출하지 않았다면? 큰 장애가 발생했을 것이다. 처음부터@Before를 사용했다면 이런 문제 자체가 발생하지 않는다.제약 덕분에 역할이 명확해진다. 다른 개발자도 이 코드를 보고 고민해야 하는 범위가 줄어들고 코드의 의도도 파악하기 쉽다.
All reactions