728x90
반응형
package pointcut;
/*
* 스프링은 아주 간단하고 효과적인 방법으로 포인트컷의 클래스와 메소드를 선정하는 알고리즘을 작성할수 있는 방법을 제공한다.
* 정규식이나 JSP,EL과 비슷한 일종의 표현식 언어를 사용해서 작성할 수 있도록 하는 방법이고
* 이것을 포인트컷 표현식 이라고 부른다.
*
* 포인트컷 표현식
* AspectJExpressionPointcut은 클래스와 메소드의 선정 알고리즘을 포인트컷 표현식을 이용해 한 번에 지정할 수 있게 해준다.
* 포인트컷 표현식은 자바의 RegEx클래스가 지원하는 정규식처럼 간단한 문자열로 복잡한 선정조건을 쉽게 만들어낼 수 있는 강력한 표현식을 지원한다.
*
* 사실 스프링이 사용하는 포인트컷 표현식은 AspectJ라는 유명 프레임워크에서 제공하는 것을 일부 가져와 확장해서 사용하기 때문에 AspectJ포인트컷 표현식이라고도 한다.
*/
// 포인트 컷의 선정 후보가 될 여러 개의 메소드를 가진 Target 클래스
public class Target implements TargetInterface{
@Override
public void hello() {
}
@Override
public void hello(String a) {
}
@Override
public int minus(int a, int b) throws RuntimeException {
return 0;
}
@Override
public int plus(int a, int b) {
return 0;
}
public void method(){
}
}
package pointcut;
public interface TargetInterface {
void hello();
void hello(String a);
int plus(int a, int b);
int minus(int a, int b);
}
package pointcut;
public class Bean {
public void method() throws RuntimeException {
}
}
package pointcut;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.junit.runner.JUnitCore;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
public class PointcutExpressionTest {
public static void main(String[] args) {
JUnitCore.main("pointcut.PointcutExpressionTest");
}
/*
* AspectJ 포인트컷 표현식은 포인트컷 지시자를 이용해 작성한다.
* 지시자 중 가장 대표적으로 사용되는 것은 execution()이다.
* execution([접근제한자] 타입패턴 [타입패턴.]이름패턴 (타입패턴|"..",...) )
* ex)
*
*/
@Test
public void methodSignaturePointcut() throws NoSuchMethodException, SecurityException{
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* minus(int,int))");
//execution( int minus(int,int)) -> return int , minus라는 메소드 이름, 두개의 int 파라미터를 가진 모든 메소드를 선정하는 포인트컷 표현식
//execution( * minus(int,int)) -> return 아무거나 , minus라는 메소드 이름, 두개의 int 파라미터를 가진 모든 메소드를 선정하는 포인트컷 표현식
//execution( * minus(..)) -> return 아무거나 , minus라는 메소드 이름, 파라미터 갯수 상관없는 모든 메소드를 선정하는 포인트컷 표현식
assertThat(pointcut.getClassFilter().matches(Target.class) &&
pointcut.getMethodMatcher().matches(
Target.class.getMethod("minus", int.class, int.class), null), is(true));
// is(true) -> 포인트컷 통과
assertThat(pointcut.getClassFilter().matches(Target.class) &&
pointcut.getMethodMatcher().matches(
Target.class.getMethod("plus", int.class, int.class), null), is(false));
// is(false) -> 메소드 매처에서 실패
assertThat(pointcut.getClassFilter().matches(Bean.class) &&
pointcut.getMethodMatcher().matches(
Target.class.getMethod("method"), null), is(false));
// is(false) -> 클래스 필터에서 실패
}
public void pointcutMatches(String expression, Boolean expected, Class<?> clazz, String methodName, Class<?>... args) throws Exception {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(expression);
// 포인트컷의 클래스 필터, 메소드 매처 두가지를 동시에 만족하는지 확인함.
assertThat(pointcut.getClassFilter().matches(clazz)
&& pointcut.getMethodMatcher().matches(clazz.getMethod(methodName, args), null),
is(expected));
}
public void tagetClassPointcutMatches(String expression, boolean... expected) throws Exception {
pointcutMatches(expression, expected[0], Target.class, "hello");
pointcutMatches(expression, expected[1], Target.class, "hello", String.class);
pointcutMatches(expression, expected[2], Target.class, "plus", int.class, int.class);
pointcutMatches(expression, expected[3], Target.class, "minus", int.class, int.class);
pointcutMatches(expression, expected[4], Target.class, "method");
pointcutMatches(expression, expected[5], Bean.class, "method");
}
@Test
public void pointcut() throws Exception {
//모든 리턴, 모튼 메서드, 파라미터 제한 없음
tagetClassPointcutMatches("execution(* *(..))", true, true, true, true, true, true);
//모든 리턴, hello메서드, 파라미터 제한 없음
tagetClassPointcutMatches("execution(* hello(..))", true, true, false, false, false, false);
//모든 리턴, hello메서드, 파라미터 없음
tagetClassPointcutMatches("execution(* hello())", true, false, false, false, false, false);
//모든 리턴, hello메서드, 1개 스트링 파라미터
tagetClassPointcutMatches("execution(* hello(String))", false, true, false, false, false, false);
//모든 리턴, meth*로 시작하는 메서드, 파라미터 제한 상관 No
tagetClassPointcutMatches("execution(* meth*(..))", false, false, false, false, true, true);
//모든 리턴, 모든 메섣, 2개 int 파라미터
tagetClassPointcutMatches("execution(* *(int,int))", false, false, true, true, false, false);
//모든 리턴, 모든 메섣, 모든 파라미터
tagetClassPointcutMatches("execution(* *())", true, false, false, false, true, true);
//모든 리턴, Target클래스의 메서드, 모든 파라미터
tagetClassPointcutMatches("execution(* pointcut.Target.*(..))", true, true, true, true, true, false);
//모든 리턴, pointcut 아래의 모든 클래스, 모든 파라미터
tagetClassPointcutMatches("execution(* pointcut.*.*(..))", true, true, true, true, true, true);
//모든 리턴, pointcut 아래의 모든 클래스, 모든 파라미터
tagetClassPointcutMatches("execution(* pointcut..*.*(..))", true, true, true, true, true, true);
//모든 리턴, com 아래의 모든 클래스, 모든 파라미터
tagetClassPointcutMatches("execution(* com..*.*(..))", false, false, false, false, false, false);
tagetClassPointcutMatches("execution(* *..Target.*(..))", true, true, true, true, true, false);
tagetClassPointcutMatches("execution(* *..Tar*.*(..))", true, true, true, true, true, false);
tagetClassPointcutMatches("execution(* *..*get.*(..))", true, true, true, true, true, false);
tagetClassPointcutMatches("execution(* *..B*.*(..))", false, false, false, false, false, true);
tagetClassPointcutMatches("execution(* *..TargetInterface.*(..))", true, true, true, true, false, false);
//메소드와 클래스와는 상관없이 예외 선언만 확인해서 메소드를 선정하는 포인트컷
//Runtime으로 시작하는 어떤 예외라도 던진다면 만족함
tagetClassPointcutMatches("execution(* *(..) throws Runtime*)", false, false, false, true, false, true);
tagetClassPointcutMatches("execution(int *(..))", false, false, true, true, false, false);
tagetClassPointcutMatches("execution(void *(..))", true, true, false, false, true, true);
}
}
반응형
'Dev > Spring' 카테고리의 다른 글
Error creating bean with name 'jpaAuditingHandler': Cannot resolve reference to bean 'jpaMappingContext' while setting constructor argument (0) | 2023.06.14 |
---|---|
Test 폴더에 있는 엔티티 -> Q class로 생성하기 (0) | 2023.05.21 |
어드바이저 = 포인트컷 + 어드바이스 (0) | 2022.12.25 |
토비스프링 1-1 정리( 개인저장용 ) (0) | 2022.10.29 |
네이버 Sens SMS API로 문자 보내기 (0) | 2022.03.30 |