1. 타입별 Advice와 Pointcut 표현식, JoinPoint의 의미를 이해할 수 있다.
2. 애너테이션을 이용한 AOP에 대해 이해하고 활용할 수 있다.
- 타입별 Advice
✔︎ Aspect를 언제 핵심 코드에 적용할지 정의
✔︎ 부가 기능에 해당
✔︎ 특정 조인 포인트에서 애스펙트에 의해 취해지는 조치
✔︎ 기본적으로 순서 보장 ❌
✔︎ 순서를 지정하고 싶으면, @Aspect
적용 단위로 org.springframwork.core.annotation.@Order
애너테이션 적용
클래스 단위
로 적용 가능✔︎ 애스펙트를 별도
의 클래스로 분리해야 함
✔︎ Before
실행 이전
에 수행void
@Before("hello.aop.order.aop.Pointcuts.orderAndService()")
public void doBefore(JoinPoint joinPoint) {
log.info("[before] {}", joinPoint.getSignature());
}
- 작업 흐름 변경 ❌
- 메서드 종료 시 자동으로 다음 타겟 호출 (예외 발생시 다음 코드 호출 ❌)
✔︎ After returning
정상 완
료 후 실행@AfterReturning(value = "hello.aop.order.aop.Pointcuts.orderAndService()", returning = "result")
public void doReturn(JoinPoint joinPoint, Object object) {
log.info("[return] {} return={}", joinPoint.getSignature(), result);
}
- 메서드 실행이 정상적으로 반환될 때 실행
- returning 속성에 사용된 이름은 어드바이스 메서드의 매개변수 이름과 일치해야 함
- returning 절에 지정된 타입의 값을 반환하는 메서드만 대상을 실행
✔︎ After throwing
예외
를 던지는 경우 실행@AfterThrowing(value = "hello.aop.order.aop.Pointcut.orderAndService()", throwing = "ex")
public void doThrowing(JoinPoint joinPoint, Exception ex) {
log.info("[ex] {} message={}", joinPoint.getSignature(), ex.getMessage());
}
- 메서드 실행이 예외를 던져서 종료될 때 실행
- throwing 속성에 사용된 이름은 어드바이스 메서드의 매개변수 이름과 일치해야 함
- throwing 절에 지정된 타입과 맞는 예외를 대상으로 실행
✔︎ After (finally)
상관없이
실행✔︎ Around
try ~ catch ~ finally
가 들어가는 구문 처리 가능ProceedingJoinPoint
사용proceed()
를 통해 대상 실행proceed()
를 통해 여러 번 실행 가능✔︎ 추가 설명
@Around
만 있어도 모든 기능 수행 가능@Before
, @After
와 같은 어드바이스는 기능은 적으나, 원하는대로 작동되고 코드도 단순@Around
만 사용해 모두 해결하는 것보다, 제약을 가지더라도 실수를 미연에 방지하는 것
- Pointcut 표현식
✔︎ 포인트컷은 관심 조인 포인트를 결정하므로, 어드바이스가 실행되는 시기를 제어할 수 있음
✔︎ AspectJ는 포인트컷을 편리하게 표현하기 위한 특별한 표현식 제공
ex) @Pointcut("execution(*hello.aop.order..*(..))")
✔︎ 예제
@Pointcut("execution(* transfer(..))") // 포인트컷 표현식
private void anyOldTransfer() {} // 포인트컷 서명
- 포인트컷 표현식은 AspectJ pointcut expression ⇒ AspectJ가 제공하는 포인트컷 표현식을 줄여 표현하는 것
✔︎ 포인트컷 표현식은 execution
같은 포인트컷 지시자(PointCut Designator, PCD)로 시작
✔︎ 포인트컷 지시자 종류
execution
을 가장 많이 사용, 나머지 자주 사용 ❌✔︎ 포인트컷 표현식은 &&
, ||
, !
를 사용하여 결합 가능
✔︎ 이름으로 pointcut 표현식 참조 가능
✔︎ 예제
@Pointcut("execution(public * * (..))")
private void anyPublicOperation() {} // (1)
@Pointcut("within(com.xyz.myapp.trading..*)")
private void inTrading() {} // (2)
@Pointcut("anyPublicOperation() && inTrading()")
private void tradingOpreation() {} // (3)
(1) `anyPublicOpreation`은 메서드 실행 조인 포인트가 공용 메서드 실행을 나타내는 경우 일치
(2) `inTrading`은 메서드 실행이 거래 모듈에 있는 경우 일치
(3) `tradingOperation`은 메서드 실행이 거래 모듈의 공개 메서드를 나타내는 경우 일치
✔︎ 일반적인 pointcut 표현식
execution(public * *(..))
set
다음 이름으로 시작하는 모든 메서드 실행execution(* set*(..))
AccountService
인터페이스에 의해 정의된 모든 메서드의 실행execution(* com.xyz.service.AccountService.*(..))
service
패키지에 정의된 메서드 실행execution(* com.xyz.service.*.*(..))
execution(* com.xyz.service..*.*(..))
within(com.xyz.service.*)
within(com.xyz.service..*)
AccountService
프록시가 인터페이스를 구현하는 모든 조인포인트 (Spring AOP에서만 메서드 실행)this(com.xyz.service.AccountService)
AccountService
대상 객체가 인터페이스를 구현하는 모든 조인포인트 (Spring AOP에서만 메서드 실행)target(com.xyz.service.AccountService)
Serializable
과 같은 모든 조인포인트 (Spring AOP에서만 메서드 실행)args(java.io.Serializable)
@Transactional
애너테이션이 있는 모든 조인포인트 (Spring AOP에서만 메서드 실행)@target(org.springframework.transaction.annotation.Transactional)
@Transactional
애너테이션이 있는 모든 조인포인트 (Spring AOP에서만 메서드 실행)@annotation(org.springframework.transaction.annotation.Transactional)
@Classified
애너테이션을 갖는 조인포인트 (Spring AOP에서만 메서드 실행)@args(com.xyz.security.Classfied)
tradeService
라는 이름을 가진 스프링 빈의 모든 조인포인트 (Spring AOP에서만 메서드 실행)bean(tradeService)
*Service
라는 이름을 가진 스프링 빈의 모든 조인포인트bean(*Service)
- JoinPoint
✔︎ 메서드 실행 위치 뿐만 아니라, 다양한 위치에 적용 가능
✔︎ 적용 가능 지점 (조인포인트) : 생성자, 필드값 접근, static 메서드 접근, 메서드 실행
✔︎ AOP를 수행하는 메서드는 이 JoinPoint 인스턴스를 인자로 받음
✔︎ JoinPoint 인스턴스에서 조인포인트 지점의 정보를 얻어야 함
✔︎ 조인포인트는 추상적인 개념, AOP를 적용할 수 있는 지점을 의미
✔︎ JoinPoint.getArgs()
: JoinPoint에 전달된 인자를 배열로 반환
✔︎ JoinPoint.getThis()
: AOP 프록시 객체를 반환
✔︎ JoinPoint.getTarget()
: AOP가 적용된 대상 객체를 반환
✔︎ JoinPoint.getSignature()
: 조언되는 메서드에 대한 설명을 반환
Signature
객체를 반환Signature
: 객체가 선언하는 모든 연산을 연산의 이름, 매개변수로 받아들이는 객체Signature
가 제공하는 메서드String getName()
: 클라이언트가 호출한 메소드의 이름을 반환String toLongString()
: 클라이언트가 호출한 메소드의 시그니처(리턴타입, 이름, 매개변수)를 패키지 경로까지 포함해서 반환String toShortString()
: 클라이언트가 호출한 메소드 시그니처를 축약한 문자열로 반환✔︎ JoinPoint.toString()
: 조언되는 방법에 대한 유용한 설명을 인쇄
✔︎ proceed()
: 다음 어드바이스나 타겟을 호출
4.애너테이션(Annotation)을 이용한 AOP
✔︎ @AspectJ
는 애너테이션이 있는 일반 Java 클래스로 관점을 선언하는 스타일
✔︎ AOP 런타임은 여전히 순수한 스프링 AOP이며, AspectJ 컴파일러나 위버에 의존 ❌
✔︎ Spring 설정에서 @AspectJ
aspect를 사용하기 위해서는 @AspectJ
aspect에 기반한 Spring AOP 설정과 이러한 aspect에 의해 조언되는 자동 프록시 빈에 대한 Spring 빈을 활성화해야함
✔︎ @AspectJ
지원은 XML 또는 Java 스타일 설정으로 활성화 가능
@AspectJ
지원 활성화 방법@Configuration
으로 @Aspect 지원을 활성화하려면 @EnableAspectJAutoProxy
애너테이션 추가@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
}
@AspectJ
지원 활성화 방법aop:aspectj-autoproxy
요소 사용<aop:aspectj-autoproxy/>
✔︎ @AspectJ 지원이 활성화되면 @AspectJ 관점(@Aspect
)이 있는 클래스로 애플리케이션 컨텍스트에 정의된 모든 빈이 Spring에서 자동으로 감지되고 Spring AOP를 구성하는데 사용
<bean id="myAspect" class="org.xyz.NotVeryUsefulAspect">
<!-- configure properties of the aspect here -->
</bean>
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class NotVeryUserfulAspect {
}
✔︎ 포인트컷은 관심 조인포인트를 결정하므로 어드바이스가 실행되는 시기 제어 가능
✔︎ Spring AOP는 Spring Bean에 대한 메소드 실행 조인포인트만 지원하므로, Pointcut은 Spring Bean의 메소드 실행과 일치하는 것으로 생각할 수 있음
✔︎ pointcut 선언은 이름과 매개변수를 포함하는 서명과 우리가 관심있는 메소드 실행을 정확히 결정하는 pointcut 표현식의 두 부분으로 구성
✔︎ pointcut 표현식은 @Pointcut
어노테이션을 사용하여 표시
✔︎ 어드바이스는 포인트컷 표현식과 연관되며, 포인트컷과 일치하는 메서드 실행 전후 또는 전후에 실행
✔︎ pointcut 표현식은 명명된 pointcut에 대한 단순 참조이거나 제자리에 선언된 pointcut 표현식일 수도 있음
☞ 어제 DI보다 수월하다 말한 것 같은데 취소다... 너무 생소한 용어들과 이론들이기에 머릿 속이 막 복잡하다 🤯 그렇지만 크루님께서는 결코 어려운 개념이 아니라고 하신다 ,, (처음이라 생소한 것 뿐..) 쫄지말고 실습과 추가 정보들을 찾아보면서 좀 더 공부해보자...!!!
TMI ) 요즘 식사를 하면서 미생이라는 드라마를 보는데 동기부여를 많이 받는 것 같다.
오늘도 고생했고 내일도 화이팅이다 :)
인생은 끝없는 반복.
반복에 지치지 않는 자가 성취한다. 드라마 '미생' 중에서 ...
・ 기술면접 (With Pair)
・ 미니 잡서칭
・ Section_2 회고