executuon은 포인트컷 지시자 라고 하는데, 포인트컷 지시자에는 execution외에도 여러가지 표현지시자들이 존재한다.
- execution : 메소드 실행 조인 포인트를 매칭한다. 스프링 AOP에서 가장 많이 사용하고, 기능도 복잡하다.
- within : 특정 타입 내의 조인 포인트를 매칭한다.
- args : 인자가 주어진 타입의 인스턴스인 조인 포인트
- this : 스프링 빈 객체(스프링 AOP 프록시)를 대상으로 하는 조인 포인트
- target : Target 객체(스프링 AOP 프록시가 가르키는 실제 대상)를 대상으로 하는 조인 포인트
- @target : 실행 객체의 클래스에 주어진 타입의 애노테이션이 있는 조인 포인트
- @within : 주어진 애노테이션이 있는 타입 내 조인 포인트
- @annotation : 메서드가 주어진 애노테이션을 가지고 있는 조인 포인트를 매칭
- @args : 전달된 실제 인수의 런타임 타입이 주어진 타입의 애노테이션을 갖는 조인 포인트
- bean : 스프링 전용 포인트컷 지시자, 빈의 이름으로 포인트컷을 지정한다.
어노테이션 인터페이스 ClassAOP
@Target의 ElementType은 코드의 위치나 범위를 나타내는 열거형 타입이며, @Target 어노테이션과 함께 사용되어, 어노테이션의 적용 범위를 제한한다.
ElementType.TYPE의 TYPE은 클래스, 인터페이스(어노테이션 타입 포함), 또는 열거형 선언에 어노테이션을 사용할 수 있음을 나타낸다.
@Retention의 RetentionPolicy는 어노테이션이 어디까지 유지되는지를 결정하며
SOURCE, CLASS, RUNTIME 으로 나뉜다.
package com.example.demo.member.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassAop {
}
어노테이션 인터페이스 MethodAOP
package com.example.demo.member.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) //메서드에 붙이는 어노테이션
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodAop {
String value();
}
서비스와 구현체
package com.example.demo.member;
public interface MemberService {
String hello(String param);
}
package com.example.demo.member;
import com.example.demo.member.annotation.ClassAop;
import com.example.demo.member.annotation.MethodAop;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@ClassAop
@Component
public class MemberServiceImpl implements MemberService{
@Override
@MethodAop("test value")
public String hello(String param) {
return "ok";
}
public String internal(String param){
return "ok";
}
}
ExecutionTest
package com.example.demo.pointcut;
import com.example.demo.member.MemberServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import java.lang.reflect.Method;
@Slf4j
public class ExecutionTest {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
Method helloMethod;
@BeforeEach
public void init() throws NoSuchMethodException {
helloMethod = MemberServiceImpl.class.getMethod("hello",String.class);
}
@Test
void printMethod(){
//public java.lang.String com.example.demo.member.MemberServiceImpl.hello(java.lang.String)
log.info("helloMethod={}",helloMethod);
}
@Test
void exactMatch() {
//public java.lang.String com.example.demo.member.MemberServiceImpl.hello(java.lang.String)
pointcut.setExpression("execution(public java.lang.String com.example.demo.member.MemberServiceImpl.hello(java.lang.String))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void allMatch() {
pointcut.setExpression("execution(* *(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void nameMatch() {
pointcut.setExpression("execution(* hello(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void nameMatchStar1() {
pointcut.setExpression("execution(* hel*(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void nameMatchStar2() {
pointcut.setExpression("execution(* *el*(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void nameMatchFalse() {
pointcut.setExpression("execution(* nono(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isFalse();
}
@Test
void packageExactMatch1() {
pointcut.setExpression("execution(* com.example.demo.member.MemberServiceImpl.hello(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void packageExactMatch2() {
pointcut.setExpression("execution(* com.example.demo.member.*.*(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void packageExactFalse() {
pointcut.setExpression("execution(* com.example.*.*(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isFalse();
}
@Test
void packageMatchSubPackage1() {
pointcut.setExpression("execution(* com.example..*.*(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
@Test
void packageMatchSubPackage2() {
pointcut.setExpression("execution(* com.example..*.*(..))");
Assertions.assertThat(pointcut.matches(helloMethod, MemberServiceImpl.class)).isTrue();
}
}
execution 문법
execution(접근제어자? 반환타입 선언타입?메서드이름(파라미터) 예외?)
- 메소드 실행 조인 포인트를 매칭한다.
- ?는 생략할 수 있다.
- * 같은 패턴을 지정할 수 있다
- '.' : 정확하게 해당 위치의 패키지
- '..' : 해당 위치의 패키지와 그 하위 패키지도 포함
'Java > 스프링 AOP' 카테고리의 다른 글
스프링 AOP - 매개변수 전달 (0) | 2023.09.16 |
---|---|
스프링 AOP - execution(2) (0) | 2023.09.14 |
Spring AOP - 어드바이스 종류 (0) | 2023.09.11 |
Spring AOP - 포인트컷 분리 (0) | 2023.09.07 |
Spring AOP 용어정리 (0) | 2023.09.06 |