개발 기록
> [AOP] 2. Aspect 생성과 지시자 사용 본문

■
1. 사용법
(1) 의존성 추가
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
(2) Aspect 구현
: 여러 클래스에 적용되는 관심사의 모듈화 구현 (ex. logging)

1. Aspect 만들기
@Aspect Annotation을 부착하여 해당 Class가 횡단관심사(부가기능) Class임을 알려준다.
★ @Aspect Annotation이 부여되었다고 해서 자동으로 Bean으로 등록되는것이 아니므로 @Component등 을 이용하여 Bean으로 등록을 해준다.
★ 이유 : Spring AOP의 경우 AOP를 제공받을 Bean를 IOC Container에 의해 생성될 때 ProxyBean을 만들어서 AOP를 제공하기 때문이다.

2. Pointcut 과 Advice 만들기
@Around("Pointcut")
2-1. Advice 생성 : @Around => 핵심관심사의 실패여부와 상관없이 전 후로 실행되도록 하는 Advice
2-2. Pointcut 설정 : @Around 의 속성값으로 PointCut 을 전달
@Around("execution(* com.java.ex.Car.accelerate(..))")
public Object logging(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().toShortString();
System.out.println(methodName + "is Start.");
Object obj = joinPoint.proceed();
return obj;
}
1. 첫번째 * 기호는 접근제어자, 반환형을 상관하지 않는다는 의미
2. com.java.ex.Car.accelerate()는 해당 Class의 파라미터가 없는 accelerate() 메소드가 호출될 때 실행
■
2. Spring JointPoint 메서드
| method name | return | 설명 |
| getSignature() | Signature | 대상 메서드의 정보 (리턴타입, 이름, 매개변수)가 저장된 Signature 객체 |
| getSignature().getName() |
String | 대상 메서드명 |
| getSignature().toLongString() | String | 대상 메서드의 패키지 경로, 리턴타입, 이름, 매개변수 |
| getSignature().toShortString() | String | 대상 메서드의 시그니처를 축약한 문자열로 리턴 |
| getTarget() | Object | 대상 메서드의 해당 클래스 객체 |
| getArgs() | Object[] | 대상 메서드를 호출할 때 넘겨준 인자 목록 |
■
3. 지시자
(1) excution
// FooDao 클래스 의 findById 메소드 실행
@Pointcut("execution(public String com.baeldung.pointcutadvice.dao.FooDao.findById(Long))")
(2) 패키지 타입으로 매칭 - within 과 @within
: 타입이 매칭되면 그 안에 모든 메서드가 매칭된다.
// 아래 두개는 의미가 같다.
@Pointcut("@within(org.springframework.stereotype.Repository)")
@Pointcut("within(@org.springframework.stereotype.Repository *)")
(3) 파라미터 타입으로 매칭 - @args 와 args
☞ args – 인수가 특정 유형인 메서드와 일치
☞ @args – 인수에 특정 주석이 달린 메서드와 일치
* 상위 타입으로도 매칭이 가능하다. (ex. args(String)은 args(Object) 로도 매칭 가능)
// 단일 매개변수를 사용하고, @Entity 주석이 달린 Bean을 파라미터로 받는 모든 메소드
@Pointcut("@args(com.baeldung.pointcutadvice.annotations.Entity)")
// 파라미터 타입을 String 으로 받는 모든 메서드
@Pointcut("args(String)")
(4)어노테이션 매칭 - @annotation
지정된 annotation 이 있는 조인 포인트에 대한 일치
// @Loggable 어노테이션이 있는 메서드
@Pointcut("@annotation(com.baeldung.pointcutadvice.annotations.Loggable)")
public void loggableMethods() {}
(5) this, target, @target
☞ this : 스프링 빈 개체(AOP 프록시)를 대상으로 하는 조인 포인트
☞ target : Target 객체(프록시가 가르키는 실제 대상)을 대상으로 하는 조인 포인트
☞ @target : 실행 객체의 클래스에 주어진 타입의 어노테이션이 있는 조인 포인트
// 대상 개체가 AccountService 인터페이스를 구현하는 모든 조인 포인트
"target(com.jbd.service.AccountService)"
// 대상 개체에 @Transactional 주석이 있는 조인 포인트
"@target(org.springframework.transaction.annotation.Transactional)"
// 프록시가 AccountService 인터페이스를 구현하는 조인 포인트와 일치
"this(com.jbd.service.AccountService)"
ex. A class 가 B interface 의 메서드를 구현한다고 했을 때
Spring AOP는 JDK 기반 프록시를 사용하며, 프록시된 객체는 Proxy 클래스 의 인스턴스가 되고 B 인터페이스를 구현하므로 아래 포인트 컷을 사용해야한다.
@Pointcut("target(com.baeldung.pointcutadvice.dao.B)")
반면에 A class 가 인터페이스를 구현하지 않거나 ProxyTargetClass 속성이 true로 설정된 경우 프록시된 개체는 A class 의 하위 클래스가 되며 아래 포인트컷을 사용한다.
@Pointcut("this(com.baeldung.pointcutadvice.dao.A)")
참고
https://backtony.github.io/spring/2021-12-29-spring-aop-2/#args
https://www.baeldung.com/spring-aop-advice-tutorial
'Spring' 카테고리의 다른 글
| > [AOP] 3. 포인트컷(PointCut)의 다양한 표현식 (0) | 2022.10.27 |
|---|---|
| > [Spring Batch] 스프링 배치 - 1. 입문 (개념과 흐름 파악) (0) | 2022.10.25 |
| > [Spring Batch] Scope(@StepScope, @JobScope) & Job Parameter - 1. Job Parameter (0) | 2022.10.17 |
| > [AOP] 1. 개념 (0) | 2022.10.04 |
| > [Spring] Spring 애플리케이션 시작 시 실행되는 로직 작성하기(@PostConstruct, ApplicationListener, CommandLineRunner 등) (0) | 2020.07.10 |