๐Ÿ”ฅ TIL - Day 82 AspectJ Pointcut ๊ธฐ๋ณธ๋ฌธ๋ฒ• (Spring AOP๋ฅผ ์ด์šฉํ•œ ํ…Œ์ŠคํŠธ)

Kim Dae Hyunยท2022๋…„ 1์›” 18์ผ
0

Spring-AOP

๋ชฉ๋ก ๋ณด๊ธฐ
4/6
post-custom-banner

Pointcut์€ AOP ์ ์šฉ์ด ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  JoinPoint ์ค‘์—์„œ ์กฐ๊ฑด์„ ํ†ตํ•ด ํŠน์ • ๋ถ€๋ถ„์— ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.

ํ”„๋ก์‹œ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” Spring AOP์˜ ๊ฒฝ์šฐ JoinPoint๊ฐ€ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ณณ์œผ๋กœ ์ œํ•œ๋˜๊ธด ํ•˜์ง€๋งŒ ๊ทธ ์‹œ์ ์ด ํ•œ ๋‘๊ฐœ๊ฐ€ ์•„๋‹ˆ๋‹ˆ ์กฐ๊ฑด์„ ํ†ตํ•œ ์ œํ•œ์€ ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•˜๋‹ค.

Pointcut์„ ์ด์šฉํ•ด์„œ ์ œํ•œํ•  ์ˆ˜ ์žˆ๋Š” ์กฐ๊ฑด์€ ์•„๋ž˜์™€ ๊ฐ™์ด ๋‹ค์–‘ํ•˜๋‹ค.

  • ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  JointPoint์— ๋งค์นญ
  • ํŠน์ • ํŒจํ‚ค์ง€ ์ดํ•˜ ๋ชจ๋“  JointPoint์™€ ๋งค์นญ
  • ํŠน์ • ๋ฉ”์„œ๋“œ ์ด๋ฆ„์— ๋งค์นญ
  • ํŠน์ • ํด๋ž˜์Šค ์ดํ•˜ ๋ชจ๋“  JointPoint์™€ ๋งค์นญ
  • ๊ฒฝ๋กœ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ฐ˜ํ™˜ํƒ€์ž…, ํŒŒ๋ผ๋ฏธํ„ฐ ๋“ฑ๊ณผ ๋งค์นญ
  • ...
  • ...

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";
    }
}

ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค

  • AspectJ ํ‘œํ˜„์‹์„ Pointcut์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด AspectJExpressionPointcut์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • ์—ฌ๋Ÿฌ๊ฐ€์ง€ Aspectํ‘œํ˜„์‹์œผ๋กœ Pointcut์œผ๋กœ TestClass์™€ ๋งค์นญํ•ด๋ณด๊ณ  ๋งค์นญ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•ด๋ณด๊ธฐ ์œ„ํ•ด 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);
    }

}

ํ˜„์žฌ ํ…Œ์ŠคํŠธ ๋Œ€์ƒ ๋ฉ”์„œ๋“œ์˜ ์ •๋ณด๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.


๐Ÿ“Œ ๋ชจ๋“  Jointpoint์— ๋งค์นญ (์ƒ๋žต๊ฐ€๋Šฅํ•œ ์กฐ๊ฑด ๋ชจ๋‘ ์ƒ๋žต)

์ƒ๋žต ๋ถˆ๊ฐ€๋Šฅํ•œ ์กฐ๊ฑด 3๊ฐœ

  • ๋ฐ˜ํ™˜ํƒ€์ž…, ๋ฉ”์„œ๋“œ์ด๋ฆ„, ํŒŒ๋ผ๋ฏธํ„ฐ
  • ์ƒ๋žต ๋ถˆ๊ฐ€๋Šฅ ํ•œ 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();
}

๐Ÿ“Œ ํŠน์ • ํŒจํ‚ค์ง€ ์ดํ•˜ ๋ชจ๋“  Jointpoint์™€ ๋งค์นญ

์˜๋„ํ•œ ๋ฐ”๋Š” 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% ์ฐธ๊ณ ํ•˜์—ฌ ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.
๊ฐ•์˜์ž๋ฃŒ๋ฅผ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์˜จ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ˆ ๋ณด๋‹ค ์ •ํ™•ํ•œ ์ •๋ณด๋ฅผ ์›ํ•œ๋‹ค๋ฉด ๊ฐ•์˜๋ฅผ ๋“ค์–ด์ฃผ์„ธ์š”. (๊ฐ•์ถ”!)
์ธํ”„๋Ÿฐ - ์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ ๊ณ ๊ธ‰ํŽธ (๊น€์˜ํ•œ ๋‹˜)

profile
์ข€ ๋” ์ฒœ์ฒœํžˆ ๊นŒ๋จน๊ธฐ ์œ„ํ•ด ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ๐Ÿง
post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€