CH02 AOP

AOP

cross cutting μ΄λΌλŠ” μš©μ–΄κ°€ 'νš‘λ‹¨μ μΈ'의 의미λ₯Ό κ°€μ§„λ‹€. AOP μ—μ„œμ˜ cross cutting concern 은 κ²°κ΅­ μœ„ κ·Έλ¦Όμ—μ„œ λ³Ό 수 μžˆλ“―μ΄ μ—¬λŸ¬ Class 듀을 두고 'νš‘λ‹¨μœΌλ‘œ λ΄€μ„λ•Œμ˜ (κ³΅ν†΅λœ) 관심사' λ₯Ό λ§ν•œλ‹€. μ—¬λŸ¬ λͺ¨λ“ˆ ν˜Ήμ€ 객체λ₯Ό κ°€λ‘œμ§€λ₯΄λŠ” κ³΅ν†΅λœ 관심사이며 이것에 λŒ€ν•œ 처리λ₯Ό λΆ„μ‚°μ‹œμΌœ 놓을 것이 μ•„λ‹ˆλΌ ν•œ κ³³μ—μ„œ λͺ¨λ“ˆν™”ν•΄μ„œ μ²˜λ¦¬ν•˜λ„λ‘ ν•˜λŠ” 것이 AOP 라고 ν•  수 μžˆλ‹€.

μ™œ 'νš‘λ‹¨'이지?

λ³΄ν†΅μ˜ λ‘œμ§μ΄λ‚˜ 클래슀λ₯Ό '쒅단'으둜 보기 λ•Œλ¬Έμ΄λ‹€. 일반적으둜 μ½”λ“œκ°€ μœ„μ—μ„œ μ•„λž˜λ‘œ 순차적으둜 μ§„ν–‰λ˜κΈ° λ•Œλ¬Έμ— μ–΄λ””μ—λ‚˜ κ³΅ν†΅μ μœΌλ‘œ 적용 λ˜λŠ”(=적용 μ‹œν‚€κ³  싢은) κ΄€μ‹¬μ‚¬λŠ” 'νš‘λ‹¨'관심사 라고 λ§ν•˜λŠ” 것이 합리적이닀.

AOP μ μš©λ°©λ²•

μ•„λž˜ JVM ꡬ성 및 흐름을 λ³΄λ©΄μ„œ AOP 적용 νƒ€μž„μ„ 더 잘 μΈμ§€ν•˜μž.

컴파일 νƒ€μž„(Compile-time)

컴파일 νƒ€μž„μ— λ°”μ΄νŠΈμ½”λ“œ μžμ²΄μ— μ›ν•˜λŠ” μ²˜λ¦¬κ°€ λ°˜μ˜λœλ‹€. μ»΄νŒŒμΌλŸ¬κ°€ 컴파일 λ‹¨κ³„μ—μ„œ AOP λ₯Ό μΈμ‹ν•˜μ—¬ μ˜λ„μ— 맞게 이λ₯Ό λ°˜μ˜ν•œ λ°”μ΄νŠΈμ½”λ“œλ₯Ό λ§Œλ“€μ–΄λ‚Έλ‹€.

λ°”μ΄νŠΈμ½”λ“œ μžμ²΄μ— 이미 반영이 λ˜μ—ˆκΈ° λ•Œλ¬Έμ— μ‹€ν–‰ μ‹œμ μ— 좔가적인 λΆ€ν•˜κ°€ λ°œμƒν•˜μ§„ μ•ŠλŠ”λ‹€. ν•˜μ§€λ§Œ 컴파일 단계에 좔가적인 μž‘μ—…μ΄ ν•„μš”ν•˜λ‹€.

λ‘œλ“œ νƒ€μž„(Load-time)

클래슀 λ‘œλ”© μ‹œμ μ— AOPλ₯Ό μ μš©ν•˜λŠ” 방식이닀. 클래슀 λ‘œλ”© 쀑에 λ°”μ΄νŠΈ μ½”λ“œλ₯Ό μˆ˜μ •ν•΄μ„œ AOP λ₯Ό μ μš©μ‹œν‚¨λ‹€. λ‘œλ“œ νƒ€μž„ μœ„λΉ™(Load-time Weaving) κΈ°λŠ₯이 μ‚¬μš©λœλ‹€. λ‘œλ“œ νƒ€μž„μ— 'λΌμ›Œλ„£λŠ”' 것이닀. 컴파일 이후에도 적용될 수 μžˆμ§€λ§Œ μ‹€ν–‰ μ‹œ μ˜€λ²„ν—€λ“œκ°€ μžˆλ‹€.

λ‘œλ“œ νƒ€μž„ μœ„λΉ™ μ‚¬μš©μ‹œμ—λŠ” 클래슀 파일 μžμ²΄μ—λŠ” 변경이 μƒκΈ°λŠ” 것이 μ•„λ‹ˆκ³ , 클래슀 λ‘œλ”κ°€ 클래슀λ₯Ό μ½μ–΄μ„œ λ©”λͺ¨λ¦¬μ— λ‘œλ“œν•  λ•Œμ— λ°”μ΄νŠΈ μ½”λ“œλ₯Ό μ‘°μž‘ν•˜μ—¬μ„œ λ©”λͺ¨λ¦¬μ— μ μž¬ν•˜λŠ” 것이닀.

λŸ°νƒ€μž„(Runtime)

μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬κ°€ μ‚¬μš©ν•˜λŠ” 방식이닀. Bean을 μƒμ„±ν• λ•Œ ν”„λ‘μ‹œ λ°©μ‹μœΌλ‘œ 객체λ₯Ό κ°μ‹Έμ„œ ν”„λ‘μ‹œ 객체λ₯Ό λ§Œλ“ λ‹€. μ΄ˆκΈ°μ— Bean 을 μƒμ„±ν• λ•Œ μ•½κ°„μ˜ λΆ€ν•˜κ°€ λ°œμƒν•˜μ§€λ§Œ μ‹€ν–‰ μ‹œμ μ—λŠ” μ˜€λ²„ν—€λ“œκ°€ μ—†λ‹€.

예λ₯Ό λ“€μ–΄ ClassA κ°€ μžˆμ„λ•Œ, 이것을 λ°”μ΄νŠΈμ½”λ“œλ‘œ λ§Œλ“€λ•Œμ™€ 클래슀 λ‘œλ“œν•˜λŠ” μ‹œμ μ— λͺ¨λ‘ 아무 ν–‰μœ„λ„ ν•˜μ§€ μ•Šμ§€λ§Œ μ΄ˆκΈ°μ— Bean 을 μƒμ„±ν•˜μ—¬ μ»¨ν…Œμ΄λ„ˆμ— λ‹΄μ„λ•Œ ν”„λ‘μ‹œ λ°©μ‹μœΌλ‘œ 객체λ₯Ό κ°μ‹Έμ„œ μ›ν•˜λŠ” μ˜λ„κ°€ 반영된 ν”„λ‘μ‹œ 객체λ₯Ό λ§Œλ“€μ–΄μ„œ Bean 을 μƒμ„±ν•œλ‹€.

μŠ€ν”„λ§μ˜ AOP

μœ„μ—μ„œ μ‚΄νŽ΄λ³Έ κ²ƒμ²˜λŸΌ λŸ°νƒ€μž„ 방식에 ν”„λ‘μ‹œ 객체λ₯Ό λ§Œλ“€μ–΄μ„œ bean 을 μƒμ„±ν•œλ‹€.

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

AbstractAutoProxyCreator κ°€ 이 역할을 λ‹΄λ‹Ήν•œλ‹€.

주석을 보면 μ•„λž˜μ™€ 같이 μ ν˜€μžˆλ‹€.

 * {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
 * that wraps each eligible bean with an AOP proxy, delegating to specified interceptors
 * before invoking the bean itself.

μ •λ¦¬ν•˜μžλ©΄ BeanPostProcessor (Factory hook that allows for custom modification of new bean instances) 의 κ΅¬ν˜„μ²΄μΈ AbstractAutoProxyCreator κ°€ Bean 생성 ν›„μ²˜λ¦¬μ— κ΄€μ—¬ν•˜μ—¬ 이λ₯Ό modify ν•΄μ„œ ν”„λ‘μ‹œ 객체 생성을 ν•˜λ©΄μ„œ λΆ€κ°€ κΈ°λŠ₯을 μ˜λ„μ— 맞게 λ„£μ–΄μ£ΌλŠ” 것이닀.

이 과정에 λŒ€ν•΄μ„œ 더 μžμ„ΈνžˆλŠ” ν† λΉ„μ˜ μŠ€ν”„λ§μ—μ„œ 닀루고 μžˆλ‹€κ³  ν•˜λŠ”λ° λ‚˜μ€‘μ— ν† λΉ„μ˜ μŠ€ν”„λ§ 정리할 λ•Œ μžμ„Ένžˆ 봐야겠닀.

Last updated