ํน์ ํ ํจ์ ํธ์ถ ์ ์ด๋ ํ์ ๊ณตํต์ ์ธ ์ฒ๋ฆฌ์ ์ฌ์ฉ๋๋ค. (๋ก๊น
, ํธ๋์ญ์
, ์ธ์ฆ)ใ
AOP์ ๊ธฐ๋ณธ ๊ฐ๋
๋ค
Aspect
์ฌ๋ฌ ํด๋์ค๋ ๊ธฐ๋ฅ์ ๊ฑธ์ณ์ ์๋ ๊ด์ฌ์ฌ, ๊ทธ๋ฆฌ๊ณ ๊ทธ๊ฒ๋ค์ ๋ชจ๋ํํ๋ ๊ฒ.
๊ฐ์ฅ ๋ง์ด ํ์ฉ๋๋ ๋ถ๋ถ์ @Transactional ๊ธฐ๋ฅ
Advice
AOP์์ ์ค์ ๋ก ์ ์ฉํ๋ ๊ธฐ๋ฅ (๋ก๊น
, ํธ๋์ญ์
, ์ธ์ฆ ๋ฑ)
Join point
Aspect ๊ฐ ์คํ๋ ์ ์๋ ์ฐ๊ฒฐ ํฌ์ธํธ
Pointcut
Join point ์ค์์ Aspect ๋ฅผ ์ ์ฉํ ๋์์ ๋ฝ์ ์กฐ๊ฑด์
Target Object
Advice๊ฐ ์ ์ฉ๋ ๋์ ์ค๋ธ์ ํธ
AOP Proxy
๋์ ์ค๋ธ์ ํธ์ Aspect ๋ฅผ ์ ์ฉํ๋ ๊ฒฝ์ฐ Advice ๋ฅผ ๋ง๋ถ์ด๊ธฐ ์ํด ํ๋ ์์
์ฃผ๋ก CGLIB (Code Generation Library, ์คํ ์ค์ ์ค์๊ฐ์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ) ํ๋ก์๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ก์ฑ ์ฒ๋ฆฌ๋ฅผ ํ๋ค.
Weaving
Advice ๋ฅผ ๋น์ฆ๋์ค ๋ก์ง ์ฝ๋์ ์ฝ์
ํ๋ ๊ฒ.
AspectJ
AOP๋ฅผ ์ ๋๋ก ์ฌ์ฉํ๊ธฐ ์ํด ๊ผญ ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณต๋๋ Spring AOP ๋ก๋ ๋ค์ํ ๊ธฐ๋ฒ์ AOP๋ฅผ ์ฌ์ฉํ ์ ์์. (Pointcut ๋ฑ)
Aspect์ ์์ฑ
package org.xyz;
import org.aspectj.lang.annotation.Aspect;
@Aspect
@Component // Component๋ฅผ ๋ถ์ธ ๊ฒ์ ํด๋น Aspect๋ฅผ ์คํ๋ง์ Bean์ผ๋ก ๋ฑ๋กํด์ ์ฌ์ฉํ๊ธฐ ์ํจ
public class UsefulAspect {
}
Pointcut ์ ์ธ
package org.xyz;
import org.aspectj.lang.annotation.Aspect;
@Aspect
@Component // Component๋ฅผ ๋ถ์ธ ๊ฒ์ ํด๋น Aspect๋ฅผ ์คํ๋ง์ Bean์ผ๋ก ๋ฑ๋กํด์ ์ฌ์ฉํ๊ธฐ ์ํจ
public class UsefulAspect {
@Pointcut("execution(* transfer(..))")
private void anyOldTransfer() {}
}
ํด๋น Aspect์ Advice ๊ฐ ์ ์ฉ๋ Join point ๋ฅผ ์ฐพ๊ธฐ ์ํ ํจํด ๋๋ ์กฐ๊ฑด ์์ฑ
ํฌ์ธํธ ์ปท ํํ์์ด๋ผ๊ณ ๋ถ๋ฆ
Pointcut ๊ฒฐํฉ
package org.xyz;
import org.aspectj.lang.annotation.Aspect;
@Aspect
@Component // Component๋ฅผ ๋ถ์ธ ๊ฒ์ ํด๋น Aspect๋ฅผ ์คํ๋ง์ Bean์ผ๋ก ๋ฑ๋กํด์ ์ฌ์ฉํ๊ธฐ ์ํจ
public class UsefulAspect {
@Pointcut("execution(public * *(..))")
private void anyPublicOperation() {} //public ๋ฉ์๋ ๋์ ํฌ์ธํธ ์ปท
@Pointcut("within(com.xyz.myapp.trading..*)")
private void inTrading() {} // ํน์ ํจํค์ง ๋์ ํฌ์ธํธ ์ปท
@Pointcut("anyPublicOperation() && inTrading()")
private void tradingOperation() {} // ์์ ๋ ์กฐ๊ฑด์ and(&&) ์กฐ๊ฑด์ผ๋ก ๊ฒฐํฉํ ํฌ์ธํธ ์ปท
}
Advice ์ ์
ํฌ์ธํธ ์ปท๋ค์ ํ์ฉํ์ฌ ํฌ์ธํธ์ปท์ ์ /ํ/์ฃผ๋ณ์์ ์คํ๋ ์ก์
์ ์ ์ํจ
Before Advice
dataAccessOperation() ์ด๋ผ๋ ๋ฏธ๋ฆฌ ์ ์๋ ํฌ์ธํธ ์ปท์ ๋ฐ๋ก ์ ์ doAccessCheck() ๊ฐ ์คํ
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class BeforeExample {
@Before("com.xyz.myapp.CommonPointcuts.dataAccessOperation()")
public void doAccessCheck() {
// ...
}
}
After Returning Advice
dataAccessOperation() ๋ผ๋ ๋ฏธ๋ฆฌ ์ ์๋ ํฌ์ธํธ์ปท์์ return ์ด ๋ฐ์๋ ํ ์คํ
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;
@Aspect
public class AfterReturningExample {
@AfterReturning("com.xyz.myapp.CommonPointcuts.dataAccessOperation()")
public void doAccessCheck() {
// ...
}
}
Around Advice
businessService() ๋ผ๋ ํฌ์ธํธ์ปท์ ์ /ํ์ ํ์ํ ๋์์ ์ถ๊ฐํจ
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
@Aspect
public class AroundExample {
@Around("com.xyz.myapp.CommonPointcuts.businessService()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
Object retVal = pjp.proceed();
// stop stopwatch
return retVal;
}
}