์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- C++
- ์ด๋๋ฆฌ์
- ํ๋ก๊ทธ๋๋ฐ
- ๊ฒฝ์ ์งํ
- ๋ง์ง
- ํด์ธ์ฌํ
- ๋ถ๋์ฐ
- ์ํธํํ
- cpp
- ๋ฐ์ด๋ธ์ค
- ๋ฏธ๊ตญ์ฌํ
- ํ์ด์ฌ
- ์๋ฆฌ์ดํธํ๋
- ๋งค๋งค์ ๋ต
- ๋นํธ์ฝ์ธ
- ์ผ์
- ์งํ
- ๊ฒฝ์
- ์ธ๊ณ๊ฒฝ์
- ํธ๋ ์ด๋
- ํธ๋ ์ด๋ฉ
- ์ฃผ์
- ์ฐจํธ๋ถ์
- ์ฌํ
- ๊ธ๋ฆฌ
- ๋ฐ์ดํฐ๋ถ์
- ํ์จ
- ๊ตญ๋ด์ฌํ
- ํฌ์
- Python
- Today
- Total
์ถ์ ๊ณต์
[Spring] AOP ์๋ฒฝ ๊ฐ์ด๋ ๋ณธ๋ฌธ
๐ Spring AOP ์๋ฒฝ ๊ฐ์ด๋: ์๋ฆฌ, ์๋/์๋ ๊ตฌํ ๋น๊ต ๋ถ์
๐ AOP(Aspect-Oriented Programming)๋?
ํ ์ค ์ ์
๋น์ฆ๋์ค ๋ก์ง๊ณผ ๊ณตํต๊ธฐ๋ฅ(๋ก๊น , ํธ๋์ญ์ , ๋ณด์ ๋ฑ)์ ๋ถ๋ฆฌํ์ฌ ๊ด๋ฆฌํ๋ ํ๋ก๊ทธ๋๋ฐ ๊ธฐ๋ฒ
AOP๋ ๋น์ฆ๋์ค ๋ก์ง๊ณผ ํก๋จ ๊ด์ฌ์ฌ(Cross-cutting Concerns)๋ฅผ ๋ถ๋ฆฌํด ์ ์ง๋ณด์๋ฅผ ์ฝ๊ฒ ํ๊ณ ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ์ ๋์ฌ์ค๋๋ค.
๐ฏ AOP๋ ์ ํ์ํ ๊น?
- ์ค๋ณต ์ฝ๋ ๊ฐ์
- ์ ์ง๋ณด์ ์ฉ์ด์ฑ ์ฆ๊ฐ
- ๊ด์ฌ์ฌ ๋ถ๋ฆฌ๋ก ์ฝ๋ ๊ฐ๋ ์ฑ ๋ฐ ํ์ง ํฅ์
- ํธ๋์ญ์ , ๋ก๊น ๊ณผ ๊ฐ์ ๋ถ๊ฐ ๊ธฐ๋ฅ์ ๊ด๋ฆฌ ํธ๋ฆฌ์ฑ ์ฆ๊ฐ
๐ AOP ๊ตฌํ ๋ฐฉ์ ๋น๊ต: ์๋ vs ์๋
๐ธ (1) AOP ์๋ ๊ตฌํ
๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ํํ๋ก AOP๋ฅผ ํ๋ด ๋ด๋ ๋ฐฉ๋ฒ์ Java์ Reflection API๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ํน์ ๊ท์น(๋ฉ์๋ ์ด๋ฆ ํจํด, ์ด๋ ธํ ์ด์ ๋ฑ)์ ๋ฐ๋ผ ๋ถ๊ฐ ๊ธฐ๋ฅ(Advice)์ ํต์ฌ ๋ก์ง ํธ์ถ ์ ํ์ ์คํ์ํค๋ ๋ฐฉ์์ ๋๋ค.
์์ ์ฝ๋ ์ดํด๋ณด๊ธฐ:
- MyClass.java: ํต์ฌ ๋น์ฆ๋์ค ๋ก์ง์ ๋ด๊ณ ์๋ ํด๋์ค์ ๋๋ค. aaa(), aaa2(), bbb() ๋ฉ์๋๋ฅผ ๊ฐ์ง๋๋ค. aaa() ๋ฉ์๋์๋ @Transactional ์ด๋ ธํ ์ด์ ์ด ๋ถ์ด ์์ต๋๋ค.
- MyAdvice.java: ๋ถ๊ฐ ๊ธฐ๋ฅ(Advice)์ ๋ด๋นํ๋ ํด๋์ค์
๋๋ค.
- invoke() ๋ฉ์๋: Reflection์ผ๋ก ์ป์ด์จ Method ๊ฐ์ฒด๋ฅผ ๋ฐ์, ํน์ ์กฐ๊ฑด(์ฌ๊ธฐ์๋ @Transactional ์ด๋ ธํ ์ด์ ์ ๋ฌด)์ ๋ง์กฑํ๋ฉด ๋ฉ์๋ ์คํ ์ ํ์ ๊ณตํต ์ฝ๋๋ฅผ ์ถ๋ ฅํ๊ณ , ์ค์ ๋ฉ์๋(m.invoke(obj, arg))๋ฅผ ํธ์ถํฉ๋๋ค.
- Pattern, matches(): (์์ ์์๋ invoke ์กฐ๊ฑด๋ฌธ์์ ์ฃผ์ ์ฒ๋ฆฌ๋์์ง๋ง) ๋ฉ์๋ ์ด๋ฆ์ด ํน์ ํจํด("a"๋ก ์์)๊ณผ ์ผ์นํ๋์ง ํ์ธํ์ฌ Advice ์ ์ฉ ๋์์ ์ ์ ํ๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ(Pointcut ์๋ฎฌ๋ ์ด์ )์ ๋ณด์ฌ์ค๋๋ค.
- AopMain.java: Reflection์ ์ฌ์ฉํ์ฌ MyClass์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , ๋ชจ๋ ๋ฉ์๋๋ฅผ ์ํํ๋ฉฐ MyAdvice์ invoke ๋ฉ์๋๋ฅผ ํตํด ํธ์ถํฉ๋๋ค.
// AopMain.java (์ผ๋ถ)
Class myClass = Class.forName("com.ABC.sbtch3.AOP.MyClass");
Object o = myClass.newInstance();
MyAdvice myAdvice = new MyAdvice();
for(Method m : myClass.getDeclaredMethods()){
myAdvice.invoke(m, o, null); // ๊ฐ ๋ฉ์๋๋ฅผ Advice๋ฅผ ํตํด ํธ์ถ
}
// MyAdvice.java (์ผ๋ถ)
class MyAdvice {
// ... Pattern p, matches() ...
void invoke(Method m, Object obj, Object... arg) throws Exception {
// @Transactional ์ด๋
ธํ
์ด์
์ด ๋ถ์ด์๋ ๋ฉ์๋์๋ง ์ /ํ ๋ถ๊ฐ๊ธฐ๋ฅ ์ ์ฉ (Pointcut ์ญํ )
if(m.getAnnotation(Transactional.class)!= null) {
System.out.println("[before]{"); // ๊ณตํต ๋ถ๊ฐ ๊ธฐ๋ฅ (Advice)
}
m.invoke(obj, arg); // ํ๊ฒ ๋ฉ์๋(ํต์ฌ ๋ก์ง) ํธ์ถ
if(m.getAnnotation(Transactional.class)!= null) {
System.out.println("}[after]"); // ๊ณตํต ๋ถ๊ฐ ๊ธฐ๋ฅ (Advice)
}
}
}
// MyClass.java (์ผ๋ถ)
class MyClass {
@Transactional // ๋ถ๊ฐ ๊ธฐ๋ฅ ์ ์ฉ ๋์์์ ํ์
void aaa() { System.out.println("aaa() is called"); }
void aaa2() { System.out.println("aaa2() is called"); }
void bbb() { System.out.println("bbb() is called"); }
}
์ฝ๋ ๋ถ์ฐ ์ค๋ช :
- invoke(Method m, Object obj, Object... arg): Reflection์ Method.invoke()๋ฅผ ์ฌ์ฉํ์ฌ ์ค์ ํ๊ฒ ๊ฐ์ฒด(obj)์ ๋ฉ์๋(m)๋ฅผ ํธ์ถํฉ๋๋ค. ์ด ํธ์ถ ์ ํ์ ๋ถ๊ฐ ๊ธฐ๋ฅ์ ์ฝ์ ํจ์ผ๋ก์จ AOP์ 'Around Advice'์ ์ ์ฌํ ๋์์ ํ๋ด ๋ ๋๋ค.
- if(m.getAnnotation(Transactional.class)!= null): ์ด ์กฐ๊ฑด๋ฌธ์ด Pointcut (๋ถ๊ฐ ๊ธฐ๋ฅ์ ์ ์ฉํ ๋์์ ์ ๋ณํ๋ ์กฐ๊ฑด)์ ์ญํ ์ ํฉ๋๋ค. ์ฌ๊ธฐ์๋ @Transactional ์ด๋ ธํ ์ด์ ์ด ๋ถ์ ๋ฉ์๋๋ง ๋์์ผ๋ก ์ผ์ต๋๋ค. ์ค์ ํธ๋์ญ์ ์ฒ๋ฆฌ๋ ์์ง๋ง, ํธ๋์ญ์ ์์/์ข ๋ฃ ๋ก์ง์ด ์ด๋ฌํ ํํ๋ก ์ ์ฉ๋ ์ ์์์ ๋ณด์ฌ์ค๋๋ค. ํธ๋์ญ์ ์ฒ๋ฆฌ๋ ๋ํ์ ์ธ ํก๋จ ๊ด์ฌ์ฌ(Cross-Cutting Concern) ์ด๋ฏ๋ก AOP ์ ์ฉ์ ๋งค์ฐ ์ ํฉํฉ๋๋ค.
- Pattern, matches(): ๋ง์ฝ ์ด๋ฆ ๊ธฐ๋ฐ์ผ๋ก ๋์์ ์ ์ ํ๊ณ ์ถ๋ค๋ฉด matches(m)์ ๊ฐ์ ์กฐ๊ฑด์ ์ฌ์ฉํ ์ ์์ต๋๋ค. Pattern.compile("a.*")์ 'a'๋ก ์์ํ๋ ๋ชจ๋ ๋ฉ์๋ ์ด๋ฆ์ ์๋ฏธํฉ๋๋ค.
์๋ ๊ตฌํ์ ํ๊ณ:
- ๋ณต์ก์ฑ: ๋ชจ๋ ๊ฐ์ฒด์ ๋ฉ์๋์ ๋ํด Reflection ์ฝ๋๋ฅผ ์์ฑํ๊ณ ์ ์ฉํ๋ ๊ฒ์ ๋งค์ฐ ๋ฒ๊ฑฐ๋กญ์ต๋๋ค.
- ์ฑ๋ฅ ์ ํ: Reflection API๋ ์ผ๋ฐ์ ์ธ ๋ฉ์๋ ํธ์ถ๋ณด๋ค ์ฑ๋ฅ์ด ๋๋ฆฝ๋๋ค.
- ์ค๋ฅ ๊ฐ๋ฅ์ฑ: ๋ฌธ์์ด ๊ธฐ๋ฐ์ ํด๋์ค/๋ฉ์๋ ์ด๋ฆ ์ฌ์ฉ, ํ์ ์ฒดํฌ์ ์ด๋ ค์ ๋ฑ์ผ๋ก ๋ฐํ์ ์ค๋ฅ ๋ฐ์ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค.
- ์ ํ์ ์ธ ๊ธฐ๋ฅ: Pointcut ํํ, ๋ค์ํ Advice ํ์ (Before, After ๋ฑ) ์ง์ ๋ฑ์ด ๋ฏธํกํฉ๋๋ค.
- ํ๋ก์ ๋ฏธ์ฌ์ฉ: ์ค์ ๊ฐ์ฒด๋ฅผ ์ง์ ํธ์ถํ๋ฏ๋ก, Spring AOP์ฒ๋ผ ํ๋ก์๋ฅผ ํตํ ์ ์ฐํ ์๋น(Weaving)์ด ์ด๋ ต์ต๋๋ค.
๐ธ (2) AOP ์๋ ๊ตฌํ (Spring AOP)
Spring Framework๋ AspectJ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ํตํฉ์ ํตํด ํจ์ฌ ๊ฐ๋ ฅํ๊ณ ํธ๋ฆฌํ AOP ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ๊ฐ๋ฐ์๋ ๋ณต์กํ Reflection ์ฝ๋ ๋์ , ์ด๋ ธํ ์ด์ ๊ณผ ์ค์ ์ผ๋ก AOP๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค. Spring AOP๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํ๋ก์(Proxy) ๊ธฐ๋ฐ์ผ๋ก ๋์ํฉ๋๋ค.
์์ ์ฝ๋ ์ดํด๋ณด๊ธฐ:
- MyMath.java: ํต์ฌ ๋น์ฆ๋์ค ๋ก์ง(๋ง์ , ๋บ์ , ๊ณฑ์ )์ ๊ฐ์ง ํ๊ฒ ํด๋์ค์ ๋๋ค. AOP ๊ด๋ จ ์ฝ๋๊ฐ ์ ํ ์์ต๋๋ค. (@Component๋ก ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋ก)
- LoggingAdvice.java: ๋ถ๊ฐ ๊ธฐ๋ฅ(๋ก๊ทธ ์ถ๋ ฅ)์ ๋ด๋นํ๋ Aspect ํด๋์ค์
๋๋ค.
- @Aspect: ์ด ํด๋์ค๊ฐ Aspect์์ ์ ์ธํฉ๋๋ค.
- @Component: Spring์ด ์ด Aspect๋ฅผ ๋น์ผ๋ก ๊ด๋ฆฌํ๋๋ก ํฉ๋๋ค.
- @Around: Advice์ ์ข ๋ฅ๋ฅผ ์ง์ ํฉ๋๋ค. (ํ๊ฒ ๋ฉ์๋ ์คํ ์ ํ ๋ฐ ์์ธ ์ฒ๋ฆฌ ๋ฑ ํฌ๊ด์ ์ ์ด ๊ฐ๋ฅ)
- "execution(* com.ABC.sbtch3.AOP.MyMath.add*(..))": Pointcut ํํ์์ ๋๋ค. com.ABC.sbtch3.AOP ํจํค์ง์ MyMath ํด๋์ค์ ์๋ ์ด๋ฆ์ด add๋ก ์์ํ๋ ๋ชจ๋ ๋ฉ์๋(๋ฆฌํด ํ์ (*), ํ๋ผ๋ฏธํฐ(..) ๋ฌด๊ด)๋ฅผ ๋์์ผ๋ก ์ง์ ํฉ๋๋ค.
- ProceedingJoinPoint pjp: ํ์ฌ Advice๊ฐ ์ ์ฉ๋ Join Point(๋ฉ์๋)์ ๋ํ ์ ๋ณด๋ฅผ ๋ด๊ณ ์์ผ๋ฉฐ, pjp.proceed()๋ฅผ ํตํด ์ค์ ํ๊ฒ ๋ฉ์๋๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค.
- Config.java: Spring ์ค์ ํด๋์ค์
๋๋ค.
- @EnableAspectJAutoProxy: ํต์ฌ ์ค์ ! ์ด ์ด๋ ธํ ์ด์ ์ด ์์ด์ผ Spring์ด @Aspect ๋น์ ์ฐพ์์ Pointcut์ ๋งค์นญ๋๋ ํ๊ฒ ๊ฐ์ฒด์ ๋ํ ํ๋ก์(Proxy) ๋ฅผ ์์ฑํ๊ณ , Advice๋ฅผ ์ ์ฉ(Weaving)ํฉ๋๋ค. ์ด๊ฒ ์์ผ๋ฉด AOP๊ฐ ์ ํ ๋์ํ์ง ์์ต๋๋ค.
- @ComponentScan: @Component, @Aspect ๋ฑ์ด ๋ถ์ ํด๋์ค๋ฅผ ์ค์บํ์ฌ ๋น์ผ๋ก ๋ฑ๋กํฉ๋๋ค.
- AopMain2.java: Spring ์ปจํ ์คํธ๋ฅผ ์คํํ๊ณ , MyMath ๋น์ ๊ฐ์ ธ์ ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค.
// Config.java (์ผ๋ถ)
@EnableAspectJAutoProxy // <<-- ์ด๊ฒ ์์ด์ผ AOP๊ฐ ํ์ฑํ๋๊ณ ํ๋ก์๊ฐ ์์ฑ๋จ!
@ComponentScan
@Configuration
class Config { }
// LoggingAdvice.java (์ผ๋ถ)
@Component // Spring Bean์ผ๋ก ๋ฑ๋ก
@Aspect // Aspect ํด๋์ค์์ ์ ์ธ
class LoggingAdvice {
// Around Advice + Pointcut ์ค์
@Around("execution(* com.ABC.sbtch3.AOP.MyMath.add*(..))")
public Object methodClassLog(ProceedingJoinPoint pjp) throws Throwable {
// ํ๊ฒ ๋ฉ์๋ ์์ ์ ๋ถ๊ฐ ๊ธฐ๋ฅ
System.out.println("<<[start]" + pjp.getSignature().getName() + Arrays.toString(pjp.getArgs()));
Object result = pjp.proceed(); // <<-- ํ๊ฒ ๋ฉ์๋(ํต์ฌ ๋ก์ง) ํธ์ถ
// ํ๊ฒ ๋ฉ์๋ ์ข
๋ฃ ํ ๋ถ๊ฐ ๊ธฐ๋ฅ
System.out.println("[end]>>" + ... + "ms");
return result;
}
}
// MyMath.java (์ผ๋ถ) - ํ๊ฒ ํด๋์ค
@Component
class MyMath {
int add(int a, int b) { /*...*/ }
int add(int a, int b, int c) { /*...*/ }
int multiply(int a, int b) { /*...*/ }
}
// AopMain2.java (์ผ๋ถ)
ApplicationContext ac = SpringApplication.run(Config.class);
MyMath mm = ac.getBean("myMath", MyMath.class); // <<-- ์ค์ ๋ก๋ MyMath์ ํ๋ก์ ๊ฐ์ฒด๊ฐ ๋ฐํ๋จ
mm.add(3,5); // -> LoggingAdvice ์ ์ฉ๋จ
mm.multiply(3,5); // -> LoggingAdvice ์ ์ฉ ์ ๋จ (Pointcut ๋ถ์ผ์น)
์ฝ๋ ๋ถ์ฐ ์ค๋ช ๋ฐ ์ด๋ ธํ ์ด์ ์ญํ :
- @EnableAspectJAutoProxy: Spring์๊ฒ AspectJ ๊ธฐ๋ฐ์ AOP ์ฒ๋ฆฌ๋ฅผ ํ์ฑํํ๋ผ๊ณ ์ง์ํฉ๋๋ค. ์ด ์ด๋ ธํ ์ด์ ์ด ์์ผ๋ฉด Spring์ @Aspect๊ฐ ๋ถ์ ๋น์ ๋ฐ๊ฒฌํด๋ ๋ฌด์ํ๊ณ ํ๋ก์๋ฅผ ์์ฑํ์ง ์์ AOP๊ฐ ์ ์ฉ๋์ง ์์ต๋๋ค. ๋ฐ๋์ ํ์ํฉ๋๋ค.
- @Aspect: LoggingAdvice ํด๋์ค๊ฐ ๋จ์ํ ๋น์ด ์๋๋ผ, Advice์ Pointcut์ ๋ด๊ณ ์๋ ํน๋ณํ Aspect ๋ชจ๋์์ Spring์๊ฒ ์๋ ค์ค๋๋ค. @EnableAspectJAutoProxy๋ @Aspect๊ฐ ๋ถ์ ๋น์ ์ฐพ์ ์ฒ๋ฆฌํฉ๋๋ค.
- @Around: ์ฌ๋ฌ Advice ํ์ ์ค ํ๋๋ก, ํ๊ฒ ๋ฉ์๋ ํธ์ถ ์ ์ฒด๋ฅผ ๊ฐ์ ์ ์์ต๋๋ค. ์ฆ, ๋ฉ์๋ ํธ์ถ ์ , ํ, ์์ธ ๋ฐ์ ์ ๋ฑ ๋ชจ๋ ์์ ์ ๊ฐ์ ํ์ฌ ๋ถ๊ฐ ๊ธฐ๋ฅ์ ์ ์ฉํ๊ณ , ์ฌ์ง์ด ํ๊ฒ ๋ฉ์๋์ ๋ฐํ ๊ฐ์ ์กฐ์ํ๊ฑฐ๋ ํธ์ถ ์์ฒด๋ฅผ ๋ง์ ์๋ ์์ต๋๋ค. (pjp.proceed() ํธ์ถ ์ฌ๋ถ)
- execution(...) (Pointcut): Advice๋ฅผ ์ด๋์ ์ ์ฉํ ์ง ๊ฒฐ์ ํ๋ ํํ์์ ๋๋ค. AspectJ Pointcut ํํ์ ๋ฌธ๋ฒ์ ์ฌ์ฉํ์ฌ ๋งค์ฐ ์ ๊ตํ๊ฒ ์ ์ฉ ๋์์ ์ง์ ํ ์ ์์ต๋๋ค. (์: ํน์ ํจํค์ง ํ์, ํน์ ์ด๋ ธํ ์ด์ ์ด ๋ถ์ ๋ฉ์๋, ํน์ ์ด๋ฆ ํจํด ๋ฑ)
- ProceedingJoinPoint pjp: @Around Advice ๋ฉ์๋์ ํ์ ํ๋ผ๋ฏธํฐ์ ๋๋ค. ํ์ฌ Advice๊ฐ ์ ์ฉ๋ ๋์ ๋ฉ์๋(Join Point)์ ๋ํ ์ ๋ณด(๋ฉ์๋ ์๊ทธ๋์ฒ, ํ๋ผ๋ฏธํฐ ๋ฑ)๋ฅผ ์ป๊ณ , pjp.proceed()๋ฅผ ํธ์ถํ์ฌ ์ค์ ํ๊ฒ ๋ฉ์๋์ ์คํ์ ์ ์ดํ ์ ์์ต๋๋ค.
- ํ๋ก์(Proxy) ๋์ ์๋ฆฌ: @EnableAspectJAutoProxy๊ฐ ํ์ฑํ๋๋ฉด, Spring์ Pointcut์ ๋งค์นญ๋๋ ๋ฉ์๋๋ฅผ ๊ฐ์ง ๋น(์ฌ๊ธฐ์๋ MyMath ๋น)์ ์์ฑํ ๋, ์ง์ MyMath ๊ฐ์ฒด๋ฅผ ๋น์ผ๋ก ๋ฑ๋กํ๋ ๋์ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ๋น์ผ๋ก ๋ฑ๋กํฉ๋๋ค. ์ด ํ๋ก์ ๊ฐ์ฒด๋ MyMath์ ๋์ผํ ์ธํฐํ์ด์ค(๋๋ ์์ ๊ตฌ์กฐ)๋ฅผ ๊ฐ์ง๋ฉฐ, ๋ด๋ถ์ ์ค์ MyMath ๊ฐ์ฒด(Target)๋ฅผ ์ฐธ์กฐํฉ๋๋ค. ํด๋ผ์ด์ธํธ(AopMain2)๊ฐ ํ๋ก์ ๊ฐ์ฒด์ ๋ฉ์๋(add())๋ฅผ ํธ์ถํ๋ฉด, ํ๋ก์๋ ๋จผ์ Aspect(LoggingAdvice)์ Advice๋ฅผ ์คํํ๊ณ , Advice ๋ด๋ถ์์ pjp.proceed()๊ฐ ํธ์ถ๋ ๋ ์ค์ MyMath ๊ฐ์ฒด์ add() ๋ฉ์๋๋ฅผ ์คํํฉ๋๋ค. multiply()์ฒ๋ผ Pointcut์ ํด๋นํ์ง ์๋ ๋ฉ์๋๋ Advice ์ ์ฉ ์์ด ๋ฐ๋ก ํ๊ฒ ๊ฐ์ฒด์ ๋ฉ์๋๊ฐ ํธ์ถ๋ฉ๋๋ค.
โป ๋น๊ต ๋ถ์: ์๋ AOP vs ์๋ AOP
๊ตฌํ ๋ณต์ก๋ | ๋์ (๋ฐ๋ณต์ ์ธ Reflection ์ฝ๋) | ๋ฎ์ (์ด๋ ธํ ์ด์ , ์ค์ ๊ธฐ๋ฐ) |
์ฑ๋ฅ | ๋ฎ์ (Reflection ์ค๋ฒํค๋) | ์๋์ ์ผ๋ก ์ฐ์ (ํ๋ก์ ์ค๋ฒํค๋, ์ต์ ํ) |
๊ธฐ๋ฅ/์ ์ฐ์ฑ | ์ ํ์ (๊ธฐ๋ณธ์ ์ธ Around ํ๋ด) | ๊ฐ๋ ฅํจ (๋ค์ํ Advice, ์ ๊ตํ Pointcut) |
์ฝ๋ ๊ฒฐํฉ๋ | ๋์ (Advice ์ฝ๋๊ฐ ํ๊ฒ ํธ์ถ ๋ก์ง๊ณผ ๊ฒฐํฉ) | ๋ฎ์ (Target ์ฝ๋๋ AOP ๋ชจ๋ฅด๊ฒ ์์ฑ ๊ฐ๋ฅ) |
- ํ๋ ์์ํฌ ํตํฉ | ์ด๋ ค์ | ์ฌ์ (Spring ์ปจํ ์คํธ์ ์๋ฒฝ ํตํฉ) |
- ํ๋ก์ ์ฌ์ฉ | ์ฌ์ฉ ์ ํจ (์ง์ ํธ์ถ ์ ์ด) | ์ฌ์ฉํจ (Dynamic Proxy ๋๋ CGLIB) |
- ํ์ค/๊ด๋ก | ๋นํ์ค์ , ํ์ต์ฉ | Spring ํ์ค, ์ค๋ฌด์์ ๋๋ฆฌ ์ฌ์ฉ |
๊ฒฐ๋ก
AOP๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ณตํต ๊ด์ฌ์ฌ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๋ถ๋ฆฌํ๊ณ ๋ชจ๋ํํ์ฌ ์ฝ๋์ ์ค๋ณต์ ์ค์ด๊ณ ์ ์ง๋ณด์์ฑ์ ๋์ด๋ ๊ฐ๋ ฅํ ํจ๋ฌ๋ค์์ ๋๋ค. ์๋ ๊ตฌํ ๋ฐฉ์(Reflection)์ AOP์ ๊ธฐ๋ณธ ์๋ฆฌ๋ฅผ ์ดํดํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ง๋ง, ์ค์ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์๋ ์ฑ๋ฅ, ๋ณต์ก์ฑ, ๊ธฐ๋ฅ ์ ํ ๋ฑ์ ํ๊ณ๊ฐ ๋ช ํํฉ๋๋ค.
๋ฐ๋ฉด, Spring AOP์ AspectJ๋ฅผ ํ์ฉํ ์๋ ๊ตฌํ ๋ฐฉ์์ @Aspect, @EnableAspectJAutoProxy ๋ฑ์ ์ด๋ ธํ ์ด์ ๊ณผ ์ค์ ์ ํตํด ํจ์ฌ ๊ฐ๊ฒฐํ๊ณ ๊ฐ๋ ฅํ๋ฉฐ ํจ์จ์ ์ผ๋ก AOP๋ฅผ ์ ์ฉํ ์ ์๊ฒ ํด์ค๋๋ค. ํนํ ํ๋ก์ ๊ธฐ๋ฐ์ผ๋ก ๋์ํ์ฌ ํ๊ฒ ์ฝ๋์ ๋ณ๊ฒฝ ์์ด ๋ถ๊ฐ ๊ธฐ๋ฅ์ ๋์ ์ผ๋ก ์๋นํ๋ ๋ฅ๋ ฅ์ Spring AOP์ ํต์ฌ ์ฅ์ ์ ๋๋ค.
๋ฐ๋ผ์ ํ๋์ ์ธ Spring ๊ธฐ๋ฐ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๋น์ฐํ Spring AOP๋ฅผ ์ฌ์ฉํ์ฌ ๋ก๊น , ํธ๋์ญ์ ๊ด๋ฆฌ, ๋ณด์ ๋ฑ ๋ค์ํ ํก๋จ ๊ด์ฌ์ฌ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ํ์ค์ ์ธ ๋ฐฉ๋ฒ์ ๋๋ค.