Pointcut์ AOP ์ ์ฉ์ด ๊ฐ๋ฅํ ๋ชจ๋ JoinPoint ์ค์์ ์กฐ๊ฑด์ ํตํด ํน์ ๋ถ๋ถ์ ์ ์ฉํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ค.
ํ๋ก์ ๋ฐฉ์์ผ๋ก ์ฌ์ฉ๋๋ Spring AOP์ ๊ฒฝ์ฐ JoinPoint๊ฐ ๋ฉ์๋๊ฐ ์คํ๋๋ ๊ณณ์ผ๋ก ์ ํ๋๊ธด ํ์ง๋ง ๊ทธ ์์ ์ด ํ ๋๊ฐ๊ฐ ์๋๋ ์กฐ๊ฑด์ ํตํ ์ ํ์ ๋ฐ๋์ ํ์ํ๋ค.
Pointcut์ ์ด์ฉํด์ ์ ํํ ์ ์๋ ์กฐ๊ฑด์ ์๋์ ๊ฐ์ด ๋ค์ํ๋ค.
Spring AOP๋ AspectJ์ Pointcut๋ฌธ๋ฒ์ ๊ทธ๋๋ก ์ฌ์ฉํ๋ค. ๊ธฐ๋ณธ์ ์ ํ์ ์๋์ ๊ฐ๋ค.
execution(์ ๊ทผ์ง์์? ๋ฐํํ์ ์ ์ธํ์ ? ๋ฉ์๋์ด๋ฆ(ํ๋ผ๋ฏธํฐ_ํ์ ) ์์ธ?)
? ๊ฐ ๋ถ์ ๋ถ๋ถ์ ์๋ต๊ฐ๋ฅํ ๋ถ๋ถ์ด๋ค. ๋ฐ๋ฉด ๊ตต์ ๋ถ๋ถ์ ์๋ต ๋ถ๊ฐ๋ฅํ๋ค.
execution ๊ณผ ๊ฐ์ Pointcut ์ง์์๋ ์ฌ๋ฌ ๊ฐ ์๋๋ฐ ๊ฐ์ฅ ๊ฐ๋ ฅํ๊ณ ๋ฒ์ฉ์ ์ธ execution์ ํตํด AspectJ Pointcut ๋ฌธ๋ฒ์ ์ตํ๋ณด์.
ํ ์คํธ ํ๊ฒฝ ๊ตฌ์ฑ
์์กด์ฑ ์ถ๊ฐ
implementation 'org.springframework.boot:spring-boot-starter-aop'
ํ
์คํธ๋ฅผ ์ํ ํด๋์ค ์์ฑ ํ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋กํ๋ค.
์คํ๋ง ๋น์ผ๋ก ๋ฑ๋ก๋์ด์ผ AOP๋ฅผ ์ ์ฉํ ์ ์์ผ๋ฏ๋ก ์ปดํฌ๋ํธ ์ค์บ์ ๋์์ด ๋๋๋ก ํ๋ค.
@Component
public class TestClass {
public String test(String str) {
return "test";
}
}
ํ ์คํธ ํด๋์ค
AspectJExpressionPointcut
์ ์ฌ์ฉํ๋ค.test
๋ฉ์๋์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ๋ค.@Slf4j
public class PointcutTest {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
Method method;
@BeforeEach
void init() throws NoSuchMethodException {
method = TestClass.class.getMethod("test", String.class);
}
@Test
void showMethodInfo() {
log.info("method = {}", method);
}
}
ํ์ฌ ํ
์คํธ ๋์ ๋ฉ์๋์ ์ ๋ณด๋ ์๋์ ๊ฐ๋ค.
์๋ต ๋ถ๊ฐ๋ฅํ ์กฐ๊ฑด 3๊ฐ
*
๋ก ์กฐ๊ฑด์์์ ๋ํ๋ธ๋ค.*
์ด ์๋ ..
๋ก ์กฐ๊ฑด์์์ ๋ํ๋ด๋๋ฐ ํ๋ผ๋ฏธํฐ์ ๊ฐ์์ ์๊ด์์์ ๋ํ๋ธ๋ค๊ณ ์ดํดํ์.@DisplayName("๋ชจ๋ Joinpoint์ ๋งค์นญ")
@Test
void allMatching() {
pointcut.setExpression("execution(* *(..))");
assertThat(pointcut.matches(method, TestClass.class)).isTrue();
}
์ ๊ทผ์ง์์: public
๋ฐํํ์
: String
์ ์ธํ์
(ํํจํค์ง): hello.aop.test.TestClass
๋ฉ์๋์ด๋ฆ: test
ํ๋ผ๋ฏธํฐํ์
: String
์ ์กฐ๊ฑด๊ณผ ์ ํํ๊ฒ ์ผ์นํ๋ ๋ฉ์๋์ ๋งค์นญ๋๋ค.
@Test
void exactMatching() {
pointcut.setExpression("execution(public String hello.aop.test.TestClass.test(String))");
assertThat(pointcut.matches(method, TestClass.class)).isTrue();
}
@DisplayName("์ ์ธํ์
(ํด๋์ค) ์ดํ ๋ชจ๋ ๋ฉ์๋์ ๋งค์นญ")
@Test
void declareTypeMatching() {
pointcut.setExpression("execution(* hello.aop.test.TestClass.*(..))");
assertThat(pointcut.matches(method, TestClass.class)).isTrue();
}
*es*
์ ๊ฐ์ด ๋ฉ์๋ ์ด๋ฆ์ ํ์ํด์ ๋ฉ์๋ ์ด๋ฆ์ ๋ํ ํจํฐ๋งค์นญ์ด ๊ฐ๋ฅํ๋ค.
@DisplayName("ํน์ ์ ์ธํ์
(ํด๋์ค) ์ดํ ๋ฉ์๋ ์ด๋ฆ ํจํด ๋งค์นญ")
@Test
void declareTypeMatching2() {
pointcut.setExpression("execution(* hello.aop.test.TestClass.*es*(..))");
assertThat(pointcut.matches(method, TestClass.class)).isTrue();
}
์๋ํ ๋ฐ๋ hello.aop ์ดํ ๋ชจ๋ JointPoint์ ๋งค์นญํ๋ ๊ฒ์ด๋ค.
hello.aop.*.*
๋ณ๋ก ์ด์ํ ๊ฒ ๊ฐ์ง ์์๋ฐ isFalse()
ํ ์คํจ ํ
์คํธ๊ฐ ์ฑ๊ณตํ๋ค.
ํน์ ํจํค์ง ์ดํ์ ๋ํ ํจํด๋งค์นญ์ ์กฐ๊ธ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ํํ๋๋ค.
@DisplayName("ํน์ ํจํค์ง ์ดํ ๋ชจ๋ Jointpoint์ ๋งค์นญ (์คํจ)")
@Test
void packageNameMatchingFailureTest() {
pointcut.setExpression("execution(* hello.aop.*.*(..))");
assertThat(pointcut.matches(method, TestClass.class)).isFalse();
}
์ฑ๊ณต ์ผ์ด์ค
hello.aop
์ดํ ๊ฒฝ๋ก๋ฅผ ํํํ ๋ ..
๋ฅผ ์ฌ์ฉํ๋ค.
..
๋ฅผ ์ฌ์ฉํ๋ฉด ํน์ ํจํค์ง ์ดํ ๊ฒฝ๋ก์ ๋งค์นญ์ด ๊ฐ๋ฅํ๋ค.
@DisplayName("ํน์ ํจํค์ง ์ดํ ๋ชจ๋ Jointpoint์ ๋งค์นญ (์ฑ๊ณต)")
@Test
void packageNameMatchingTest() {
pointcut.setExpression("execution(* hello.aop..*.*(..))");
assertThat(pointcut.matches(method, TestClass.class)).isTrue();
}
๊ธฐ์ตํ์!!
execution(์ ๊ทผ์ง์์? ๋ฐํํ์
์ ์ธํ์
(ํจํค์ง๊น์ง)? ๋ฉ์๋์ด๋ฆ(ํ๋ผ๋ฏธํฐ) ์์ธ?)
์๋ต๋ถ๊ฐ๋ฅ: ๋ฐํํ์
, ๋ฉ์๋์ด๋ฆ, ํ๋ผ๋ฏธํฐ
์๋ ๊ฐ์๋ฅผ 100% ์ฐธ๊ณ ํ์ฌ ์ ๋ฆฌํ ๋ด์ฉ์
๋๋ค.
๊ฐ์์๋ฃ๋ฅผ ๊ทธ๋๋ก ๊ฐ์ ธ์จ ๊ฒ์ ์๋๋ ๋ณด๋ค ์ ํํ ์ ๋ณด๋ฅผ ์ํ๋ค๋ฉด ๊ฐ์๋ฅผ ๋ค์ด์ฃผ์ธ์. (๊ฐ์ถ!)
์ธํ๋ฐ - ์คํ๋ง ํต์ฌ ์๋ฆฌ ๊ณ ๊ธํธ (๊น์ํ ๋)