AOP
μ΄ν리μΌμ΄μ
μ 체μ μ¬μ©λλ κΈ°λ₯μ μ¬μ¬μ© νλλ‘ μ§μ νλκ²μ΄λ€.
μ¬κΈ°μμ κ΄μ μ κΈ°μ‘΄μ μλ°λ₯Ό κ°λ°νλ ν΅μ¬ λͺ¨λμ λν κ΄μ μμ λΆκ°κΈ°λ₯μ κ΄μ μΌλ‘ λ°κΎΈμ΄ νλ‘κ·Έλλ° νλ κ²μ΄λ€.
μ΄λ μ΄ν리μΌμ΄μ μ κ°λ°μ μν΄ λΉμ§λμ€ λ‘μ§κ³Ό μΈνλΌ λ‘μ§μ΄ μλλ° μ΄ λμ μ°¨μ΄μ μ λ€μκ³Ό κ°λ€.
- λΉμ§λμ€ λ‘μ§ : λ°μ΄ν°μ μνκ°μ μ‘°μνλ λ‘μ§
- μΈνλΌ λ‘μ§ : κΆν 체ν¬, νΈλμ μ , λ‘κΉ λ± λΉμ§λμ€ λ‘μ§μ μ€νμ μν κΈ°λ° λ‘μ§
AOP λ μ΄ μΈνλΌ λ‘μ§μ μ€λ³΅μ±μ μ κ±°νλκ²μ λͺ©ν λ₯Ό λκ³ μλ€.
μ΄λ κ΄μ¬μ λΆλ¦¬ (Seperation of Concerns) λ₯Ό ν΅νμ¬ ν΅μ¬ κ΄μ¬ μ¬νμ μ§μ€ νλκ²μ΄λ€.
κΈ°λ₯μ ν΅μ¬ λΉμ§λμ€ λ‘μ§κ³Ό κ³΅ν΅ λͺ¨λλ‘ λΆλ¦¬νκ³ , ν΅μ¬ λ‘μ§μ μν₯μ λ―ΈμΉμ§ μκ³ μ¬μ΄μ¬μ΄μ κ³΅ν΅ λͺ¨λμ ν¨κ³Όμ μΌλ‘ μ λΌμ λ£λλ‘ μ½λλ°μμ μ€μ λλ€λ κ²μ΄ ν΅μ¬μ΄λ€.
νλ‘κ·Έλ¨ νμ μ΄ νλ€κΈ° λλ¬Έμ AOP μ μ¬μ©μ΄ λ§μ κ²½μ°μλ μ μ§λ³΄μμ κ΄λ¦¬μ μΈ μΈ‘λ©΄μ΄ μ΄λ €μμ΄ λ§λ€.
νΉμ§
μ₯μ
- μ€λ³΅λλ μ½λ μ κ±°
- ν¨μ¨μ μΈ μ μ§λ³΄μ
- λμ μμ°μ±
- μ¬νμ©μ± κ·Ήλν
- μ μ°ν λ³ν μμ©
λ¨μ
- AOP κ° λ§μΌλ©΄ κ΄λ¦¬κ° μ΄λ ΅λ€.
μ£Όμκ°λ
- Aspect
- μ¬λ¬ κ°μ²΄μ 곡ν΅μΌλ‘ μ μ©λλ ν‘λ¨ κ΄μ¬ λͺ¨λμ μ μ
- Joinpoint
- Advice λ₯Ό μ μ© κ°λ₯ν μ§μ μΌλ‘ Method λ₯Ό νΈμΆ
- νλ κ° λ³κ²½μ΄ ν΄λΉ
- Spring μμλ Method νΈμΆλ§ μ§μ
- Interceptor
- Interceptor Chain λ°©μμ AOP ν΄μμ μ¬μ©λλ μ©μ΄λ‘μ μ£Όλ‘ νκ°μ νΈμΆ Method λ₯Ό κ°μ§λ Advice
- Advice
- μΈμ , μ΄λ€ κ³΅ν΅ κ΄μ¬ κΈ°λ₯μ ν΅μ¬ κ΄μ¬ λͺ¨λμ μ μ©ν μ§λ₯Ό μ μ
- Weaving
- Advice λ₯Ό ν΅μ¬ κ΄μ¬ λͺ¨λμ μ μ©νλ κ²μ μ μ
- Pointcut
- ν‘λ¨ κ΄μ¬ λͺ¨λμ΄ μ μ©λ λ©μλλ₯Ό μ μ νλ λ°©λ²μΌλ‘ μ€νλ§μμλ μ κ· ννμμ΄λ Aspect J λ¬Έλ²μ ν΅ν΄ μ μ
Advice
μ μ’
λ₯
- Before
- λμ κ°μ²΄μ Method νΈμΆ μ μ€ν
- After Returning
- λμ κ°μ²΄κ°
Exception
μμ΄ μ μμ μΌλ‘ μ€νλ ν μ€ν
- λμ κ°μ²΄κ°
- After Throwing
- λμ κ°μ²΄μ
Exception
κ³Ό μκ΄μμ΄ μ€ν finally
μ κΈ°λ₯κ³Ό λΉμ·ν¨
- λμ κ°μ²΄μ
- Around
- λμ κ°μ²΄μ λ©μλ νΈμΆ μ , ν λλ
Exception
λ°μ μμ μ μ€ν
- λμ κ°μ²΄μ λ©μλ νΈμΆ μ , ν λλ
μ μ©
Weaving λ°©μ
Advice λ₯Ό Weaving νλ λ°©μμλ μΈκ°μ§ λ°©μμ΄ μ‘΄μ¬νλ€.
- μ»΄νμΌμμ
Weaving
νκΈ° - ν΄λμ€ λ‘λ© μμ
Weaving
νκΈ° - λ°νμμμ
Weaving
νκΈ°
Spring AOP λ?
μ€νλ§μ μ체μ μΌλ‘ νλ‘μ κΈ°λ°μ AOP λ₯Ό μ§μνκ³ μλ€.
μ€νλ§ AOP λ λ©μλ νΈμΆ JoinPoint
λ§ μ§μνλ€.
μ€νλ§μ 3κ°μ§ λ°©μμ AOP λ₯Ό μ§μνλ€.
- XML μ€ν€λ§ κΈ°λ°μ POJO ν΄λμ€λ₯Ό μ΄μ©ν AOPꡬν
- AspectJ μμ μ μν
@Aspect
μ΄λ Έν μ΄μ κΈ°λ°μ AOP ꡬν - μ€νλ§ API λ₯Ό μ΄μ©ν AOP ꡬν
νλ‘μ κ°μ²΄λ₯Ό μμ±νλ λ°©μμ λμ κ°μ²΄κ° μΈν°νμ΄μ€λ₯Ό ꡬννκ³ μλμ§ μ¬λΆμ λ°λΌμ 2κ°μ§ λ°©μμΌλ‘ λλ©λλ€.
- JDK Dynamic Proxy
- μλ°μ 리νλ μ
API λ₯Ό μ 곡νλ
java.lang.reflect.Proxy
λ₯Ό μ΄μ©νμ¬ νλ‘μ κ°μ²΄λ₯Ό μμ±ν©λλ€. - μΈν°νμ΄μ€λ₯Ό κΈ°λ°μΌλ‘ νλ‘μ κ°μ²΄λ₯Ό μμ±νκΈ° λλ¬Έμ μΈν°νμ΄μ€μ μ μλμ§ μλ λ©μλμ λν΄μλ AOP κ° μ μ©λμ§ μλ μ μ μ μν΄μΌ νλ€.
- μλ°μ 리νλ μ
API λ₯Ό μ 곡νλ
- CGLIB (Code Generation Library)
- λμ κ°μ²΄κ° μΈν°νμ΄μ€λ₯Ό ꡬννκ³ μμ§ μκ³ λ°λ‘ ν΄λμ€λ‘ μ¬μ©ν λ νλ‘μ κ°μ²΄λ₯Ό μμ±
- λμ ν΄λμ€λ₯Ό λ°λ‘ μμ λ°μ νλ‘μλ₯Ό ꡬννλ€.
- ν΄λμ€κ°
final
μΈ κ²½μ°μλ νλ‘μλ₯Ό μμ±ν μ μλ€.
Spring Boot AOP μ μ©
package com.square.common.advice;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Order(0)
public class LoggerAdvice {
private static final Logger logger = LoggerFactory.getLogger(LoggerAdvice.class);
@Before("execution(* com.square..controller.*Controller.*(..))")
public void logServiceAccessBefore(JoinPoint joinPoint) throws Throwable{
logger.info("Logger Advice Before");
}
@After("execution(* com.square..controller.*Controller.*(..))")
public void logServiceAccessAfter(JoinPoint joinPoint) throws Throwable{
logger.info("Logger Advice After");
}
@AfterReturning(pointcut="execution(* com.square..controller.*Controller.*(..))", returning="str")
public void logServiceAccessAfterReturning(JoinPoint joinPoint, Object str) throws Throwable{
logger.info("Returning is " + str);
logger.info("Logger Advice AfterReturning");
}
@Pointcut("execution(* com.square..controller.*Controller.*(..))")
public void logServiceAccessPointcut() {}
@Before("logServiceAccessPointcut()")
public void logServiceAccessPointcutBefore(JoinPoint joinPoint) {
logger.info("[Pointcut] Logger Advice Before");
}
@After("logServiceAccessPointcut()")
public void logServiceAccessPointcutAfter(JoinPoint joinPoint) {
logger.info("[Pointcut] Logger Advice After");
}
@AfterReturning(value="logServiceAccessPointcut()", returning="str")
public void logServiceAccessPointcutAfterReturning(JoinPoint joinPoint, Object str) {
logger.info("[Pointcut] Returning is " + str);
logger.info("[Pointcut] Logger Advice AfterReturning");
}
@Around("execution(* com.square..controller.*Controller.*(..))")
public Object logServiceAccessPointcutAround(ProceedingJoinPoint processedJoinPoint) throws Throwable {
logger.info("[Pointcut] Logger Advice Around Before");
Object obj = processedJoinPoint.proceed();
logger.info("[Pointcut] Logger Advice Around After");
return obj;
}
}
AOP μ μ© λμ νμ΄μ§λ₯Ό νΈμΆνλ©΄ λ€μκ³Ό κ°μ΄ λ‘κ·Έκ° λ¨λλ€.
[Pointcut] Logger Advice Around Before
Logger Advice Before
[Pointcut] Logger Advice Before
##
# 컨νΈλ‘€λ¬ λ‘μ§ μ²λ¦¬
##
[Pointcut] Logger Advice Around After
Logger Advice After
[Pointcut] Logger Advice After
Returning is index
Logger Advice AfterReturning
[Pointcut] Returning is index
[Pointcut] Logger Advice AfterReturning