Chapter 6 - KOO-YS/toby-spring GitHub Wiki


AOP


Goals

  • IoC/DI, μ„œλΉ„μŠ€ 좔상화와 λ”λΆˆμ–΄ μŠ€ν”„λ§μ˜ 3λŒ€ 기반 기술의 ν•˜λ‚˜μΈ AOP의 필연적인 λ“±μž₯ λ°°κ²½κ³Ό μŠ€ν”„λ§μ΄ 그것을 λ„μž…ν•œ 이유, μ μš©μ„ 톡해 얻을 수 μžˆλŠ” μž₯점이 무엇인지 μΆ©λΆ„ν•œ 이해가 ν•„μš”ν•˜λ‹€.

🌱 Branch chapter06 folder μ‚¬μš©


6.1 νŠΈλžœμž­μ…˜ μ½”λ“œμ˜ 뢄리



🌱 Branch chapter06/refactor6.1에 μ‹€μŠ΅ 적용



λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ λ‹΄λ‹Ήν•˜λŠ” μ½”λ“œκ°€ νŠΈλžœμž­μ…˜μ˜ μ‹œμž‘κ³Ό μ’…λ£Œ μž‘μ—… μ‚¬μ΄μ—μ„œ μˆ˜ν–‰λ˜μ–΄μ•Ό ν•œλ‹€λŠ” 사항을 μ§€ν‚€λ˜, 성격이 λ‹€λ₯Έ μ½”λ“œλ₯Ό 두 개의 λ©”μ†Œλ“œλ‘œ 뢄리

UserService implements : UserServiceImpl & UserServiceTx


Q. νƒ€μž…μœΌλ‘œ ν•˜λ‚˜μ˜ λΉˆμ„ κ²°μ •ν•  수 μ—†λŠ” 경우(νƒ€μž…μ„ κ°€μ§„ 빈이 2개 이상), ν•„λ“œ 이름을 μ΄μš©ν•΄ λΉˆμ„ μ°ΎλŠ”λ‹€
@Autowired
UserService userServiceTx;		// ν•„λ“œ μ΄λ¦„μœΌλ‘œ 검색

νŠΈλžœμž­μ…˜ 경계섀정 μ½”λ“œμ˜ 뢄리와 DIλ₯Ό ν†΅ν•œ 연결을 톡해 얻을 수 μžˆλŠ” μž₯점
  • λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ λ‹΄λ‹Ήν•˜κ³  μžˆλŠ” UserServiceImpl의 μ½”λ“œλ₯Ό μž‘μ„±ν•  λ•ŒλŠ” νŠΈλžœμž­μ…˜κ³Ό 같은 기술적인 λ‚΄μš©μ—λŠ” μ „ν˜€ μ‹ κ²½μ“°μ§€ μ•Šμ•„λ„ λœλ‹€
  • λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ— λŒ€ν•œ ν…ŒμŠ€νŠΈλ₯Ό μ†μ‰½κ²Œ λ§Œλ“€μ–΄λ‚Ό 수 μžˆλ‹€

6.2 고립된 λ‹¨μœ„ ν…ŒμŠ€νŠΈ



🌱 Branch chapter06/refactor6.2에 μ‹€μŠ΅ 적용



κ°€μž₯ νŽΈν•˜κ³  쒋은 ν…ŒμŠ€νŠΈ 방법은 κ°€λŠ₯ν•œ ν•œ μž‘μ€ λ‹¨μœ„λ‘œ μͺΌκ°œμ„œ ν…ŒμŠ€νŠΈν•˜λŠ” 것

μž‘μ€ λ‹¨μœ„ ν…ŒμŠ€νŠΈκ°€ 쒋은 이유

  • ν…ŒμŠ€νŠΈκ°€ μ‹€νŒ¨ν–ˆμ„ λ•Œ κ·Έ 원인을 μ°ΎκΈ° 쉽닀
  • ν…ŒμŠ€νŠΈμ˜ μ˜λ„λ‚˜ λ‚΄μš©μ΄ λΆ„λͺ…ν•΄μ§„λ‹€
  • ν…ŒμŠ€νŠΈλ₯Ό μž‘μ„±ν•˜κΈ° 쉽닀

ν•˜μ§€λ§Œ, ν…ŒμŠ€νŠΈ λŒ€μƒμ΄ λ‹€λ₯Έ μ˜€λΈŒμ νŠΈμ™€ ν™˜κ²½μ— μ˜μ‘΄ν•˜κ³  μžˆλ‹€λ©΄ μž‘μ€ λ‹¨μœ„μ˜ ν…ŒμŠ€νŠΈκ°€ μ£ΌλŠ” μž₯점을 μ–»κΈ° νž˜λ“€λ‹€


ν…ŒμŠ€νŠΈ λŒ€μƒ 였브젝트 고립

ν…ŒμŠ€νŠΈμ˜ λŒ€μƒμ΄ ν™˜κ²½μ΄λ‚˜, μ™ΈλΆ€ μ„œλ²„, λ‹€λ₯Έ 클래슀의 μ½”λ“œμ— μ’…μ†λ˜κ³  영ν–₯을 λ°›μ§€ μ•Šλ„λ‘ κ³ λ¦½μ‹œν‚¬ ν•„μš”κ°€ μžˆλ‹€.

ν…ŒμŠ€νŠΈλ₯Ό 의쑴 λŒ€μƒμœΌλ‘œλΆ€ν„° λΆ„λ¦¬ν•΄μ„œ κ³ λ¦½μ‹œν‚€λŠ” 방법은 ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•œ λŒ€μ—­μ„ μ‚¬μš©ν•˜λŠ” 것

그런데 의쑴 μ˜€λΈŒμ νŠΈλ‚˜ μ™ΈλΆ€ μ„œλΉ„μŠ€μ— μ˜μ‘΄ν•˜μ§€ μ•ŠλŠ” 고립된 ν…ŒμŠ€νŠΈ 방식을 λ§Œλ“€μ—ˆμ„ λ•Œ, κΈ°λŠ₯이 μˆ˜ν–‰μ΄ λ˜λ„ κ·Έ κ²°κ³Ό 기둝이 λ‚¨μ§€μ•Šμ•„ 직접 κ²°κ³Όλ₯Ό κ²€μ¦ν•˜κΈ° νž˜λ“€λ‹€

-> ν…ŒμŠ€νŠΈ λŒ€μƒκ³Ό ν˜‘λ ₯ 였브젝트 사이에 μ£Όκ³  받은 정보λ₯Ό μ €μž₯ν•΄λ’€λ‹€κ°€, ν…ŒμŠ€νŠΈ 검증에 μ‚¬μš©ν•  수 μžˆκ²Œν•˜λŠ” λͺ© 였브젝트λ₯Ό λ§Œλ“€μ–΄μ•Όν•œλ‹€.

ν…ŒμŠ€νŠΈ μˆ˜ν–‰ μ„±λŠ₯의 ν–₯상

  • λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ κ²€μ¦ν•˜λŠ” 데 μ§μ ‘μ μœΌλ‘œ ν•„μš”ν•˜μ§€ μ•Šμ€ 의쑴 μ˜€λΈŒμ νŠΈμ™€ μ„œλΉ„μŠ€λ₯Ό λͺ¨λ‘ μ œκ±°ν•˜κ³ , ν•„μš”ν•œ 뢀뢄은 λͺ© 였브젝트λ₯Ό 생성해 μ΅œμ†Œν™”ν•œλ‹€

    • ν…ŒμŠ€νŠΈ μˆ˜ν–‰μ‹œκ°„μ΄ 훨씬 큰 차이둜 μ§§μ•„μ‘Œλ‹€.
    • ν…ŒμŠ€νŠΈ μˆ˜ν–‰ μ„±λŠ₯이 크게 ν–₯μƒλ˜μ—ˆλ‹€
    • ν…ŒμŠ€νŠΈκ°€ λ‹€λ₯Έ 의쑴 λŒ€μƒμ— 영ν–₯을 받을 경우 λŒ€λΉ„ν•΄ λ³΅μž‘ν•˜κ²Œ μ€€λΉ„ν•  ν•„μš”κ°€ μ—†λ‹€
λ‹¨μœ„ ν…ŒμŠ€νŠΈ

ν…ŒμŠ€νŠΈ λŒ€μƒ 클래슀λ₯Ό λͺ© 였브젝트 λ“±μ˜ ν…ŒμŠ€νŠΈ λŒ€μ—­μ„ μ΄μš©ν•΄ 의쑴 μ˜€λΈŒμ νŠΈλ‚˜ μ™ΈλΆ€μ˜ λ¦¬μ†ŒμŠ€λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šλ„λ‘ κ³ λ¦½μ‹œμΌœμ„œ ν…ŒμŠ€νŠΈν•˜λŠ” 것

톡합 ν…ŒμŠ€νŠΈ

두 개 μ΄μƒμ˜, μ„±κ²©μ΄λ‚˜ 계측이 λ‹€λ₯Έ μ˜€λΈŒμ νŠΈκ°€ μ—°λ™ν•˜λ„λ‘ λ§Œλ“€μ–΄ ν…ŒμŠ€νŠΈν•˜κ±°λ‚˜, μ™ΈλΆ€ DBλ‚˜ 파일, μ„œλΉ„μŠ€ λ“±μ˜ λ¦¬μ†ŒμŠ€κ°€ μ°Έμ—¬ν•˜μ—¬ ν•˜λŠ” ν…ŒμŠ€νŠΈ

λ‹¨μœ„ ν…ŒμŠ€νŠΈ vs 톡합 ν…ŒμŠ€νŠΈ 선택 κ°€μ΄λ“œλΌμΈ

  • λ‹¨μœ„ ν…ŒμŠ€νŠΈλ₯Ό μš°μ„ μ‹œ
  • μ™ΈλΆ€μ™€μ˜ μ˜μ‘΄κ΄€κ³„λ₯Ό μ΅œμ†Œν™”ν•˜κ³  ν•„μš”μ— 따라 μŠ€ν…μ΄λ‚˜ λͺ© 였브젝트 λ“±μ˜ ν…ŒμŠ€νŠΈ λŒ€μ—­μ„ 이용
  • μ™ΈλΆ€ λ¦¬μ†ŒμŠ€λ₯Ό μ‚¬μš©ν•΄μ•Όλ§Œ κ°€λŠ₯ν•œ ν…ŒμŠ€νŠΈλŠ” 톡합 ν…ŒμŠ€νŠΈλ‘œ λ§Œλ“¦
  • λ‹¨μœ„ ν…ŒμŠ€νŠΈλ‘œ λ§Œλ“€κΈ° λ„ˆλ¬΄ λ³΅μž‘ν•˜λ‹€κ³  νŒλ‹¨μ΄ λœλ‹€λ©΄, μ²˜μŒλΆ€ν„° 톡합 ν…ŒμŠ€νŠΈλ₯Ό κ³ λ €. 톡합 ν…ŒμŠ€νŠΈ μ°Έμ—¬ μ½”λ“œ 쀑 μ΅œλŒ€ν•œ λ§Žμ€ 뢀뢄을 미리 λ‹¨μœ„ ν…ŒμŠ€νŠΈλ‘œ 검증해두기
  • μŠ€ν”„λ§ ν…ŒμŠ€νŠΈ μ»¨ν…μŠ€νŠΈ ν”„λ ˆμž„μ›Œν¬λ₯Ό μ΄μš©ν•˜λŠ” ν…ŒμŠ€νŠΈλŠ” 톡합 ν…ŒμŠ€νŠΈλ‹€

λͺ© ν”„λ ˆμž„μ›Œν¬

  • λ‹¨μœ„ ν…ŒμŠ€νŠΈλ₯Ό λ§Œλ“€κΈ° μœ„ν•΄μ„œλŠ” μŠ€ν…μ΄λ‚˜ λͺ© 였브젝트의 μ‚¬μš©μ΄ ν•„μˆ˜μ μ΄λ‹€

  • λŒ€ν‘œμ  ν”„λ ˆμž„μ›Œν¬ : Mockito

    • Mockito둜 λ§Œλ“€μ–΄μ§„ λͺ© μ˜€λΈŒμ νŠΈλŠ” λ©”μ†Œλ“œμ˜ 호좜과 κ΄€λ ¨λœ λͺ¨λ“  λ‚΄μš©μ„ μžλ™μœΌλ‘œ μ €μž₯해두고, 이λ₯Ό κ°„λ‹¨ν•œ λ©”μ†Œλ“œλ‘œ 검증할 수 있게 ν•΄μ€€λ‹€
    1. μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ΄μš©ν•΄ λͺ© 였브젝트λ₯Ό λ§Œλ“ λ‹€
    2. λͺ© μ˜€λΈŒμ νŠΈκ°€ 리턴할 값이 있으면 이λ₯Ό μ§€μ •ν•΄μ€€λ‹€. λ©”μ†Œλ“œκ°€ 호좜되면 μ˜ˆμ™Έλ₯Ό κ°•μ œλ‘œ λ˜μ§€κ²Œ λ§Œλ“€ 수 μžˆλ‹€
    3. ν…ŒμŠ€νŠΈ λŒ€μƒ μ˜€λΈŒμ νŠΈμ— DI ν•΄μ„œ λͺ© μ˜€λΈŒμ νŠΈκ°€ ν…ŒμŠ€νŠΈ 쀑에 μ‚¬μš©λ˜λ„λ‘ λ§Œλ“ λ‹€
    4. ν…ŒμŠ€νŠΈ λŒ€μƒ 였브젝트λ₯Ό μ‚¬μš©ν•œ 후에 λͺ© 였브젝트의 νŠΉμ • λ©”μ†Œλ“œκ°€ ν˜ΈμΆœλλŠ”μ§€, μ–΄λ–€ 값을 κ°€μ§€κ³  λͺ‡ 번 ν˜ΈμΆœλλŠ”μ§€ 검증
    • any() : νŒŒλΌλ―Έν„° λ‚΄μš©μ€ λ¬΄μ‹œν•˜κ³  호좜 횟수만 확인 κ°€λŠ₯
    • times() : λ©”μ†Œλ“œ 호좜 횟수λ₯Ό 검증해쀀닀
    • ArgumentCaptor : νŒŒλΌλ―Έν„°λ₯Ό 직접 λΉ„κ΅ν•˜κΈ°λ³΄λ‹€λŠ” νŒŒλΌλ―Έν„°μ˜ λ‚΄λΆ€ 정보λ₯Ό 확인해야 ν•˜λŠ” κ²½μš°μ— 유용
  • λͺ© ν”„λ ˆμž„μ›Œν¬μ˜ νŠΉμ§•

    • λͺ© 클래슀λ₯Ό 일일이 μ€€λΉ„ν•΄λ‘˜ ν•„μš”κ°€ μ—†λ‹€
    • κ°„λ‹¨ν•œ λ©”μ†Œλ“œ 호좜만으둜 λ‹€μ΄λ‚΄λ―Ήν•˜κ²Œ νŠΉμ • μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ ν…ŒμŠ€νŠΈμš© λͺ© 였브젝트λ₯Ό λ§Œλ“€ 수 μžˆλ‹€

6.3 λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œμ™€ νŒ©ν† λ¦¬ 빈



🌱 Branch chapter06/refactor6.3에 μ‹€μŠ΅ 적용



ν”„λ‘μ‹œ (proxy)

  • μžμ‹ μ΄ ν΄λΌμ΄μ–ΈνŠΈκ°€ μ‚¬μš©ν•˜λ €κ³  ν•˜λŠ” μ‹€μ œ λŒ€μƒμΈ 것 처럼 μœ„μž₯ν•΄μ„œ ν΄λΌμ΄μ–ΈνŠΈμ˜ μš”μ²­μ„ λ°›μ•„μ£ΌλŠ” 것

  • λŒ€λ¦¬μž, λŒ€λ¦¬μΈκ³Ό 같은 역할을 ν•œλ‹€

  • 타깃(target) or 싀체(real subject) : ν”„λ‘μ‹œλ₯Ό 톡해 μ΅œμ’…μ μœΌλ‘œ μš”μ²­μ„ μœ„μž„λ°›μ•„ μ²˜λ¦¬ν•˜λŠ” μ‹€μ œ 였브젝트

  • ν”„λ‘μ‹œμ˜ νŠΉμ§•
    • 타깃과 같은 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„
    • ν”„λ‘μ‹œκ°€ 타깃을 μ œμ–΄ν•  수 μžˆλŠ” μœ„μΉ˜μ— μžˆλ‹€λŠ” 것
  • ν”„λ‘μ‹œμ˜ ꡬ뢄 (μ‚¬μš© λͺ©μ μ— λ”°λ₯Έ)
    1. ν΄λΌμ΄μ–ΈνŠΈκ°€ 타깃에 μ ‘κ·Όν•˜λŠ” 방법을 μ œμ–΄ν•˜κΈ° μœ„ν•œ λͺ©μ 
    2. 타깃에 뢀가적인 κΈ°λŠ₯을 λΆ€μ—¬ν•΄μ£ΌκΈ° μœ„ν•œ λͺ©μ 
    • 두 κ°€μ§€ λͺ¨λ“œ λŒ€λ¦¬ μ˜€λΈŒμ νŠΈλΌλŠ” κ°œλ…μ˜ ν”„λ‘μ‹œλ₯Ό 두고 μ‚¬μš©ν•œλ‹€λŠ” 점은 λ™μΌν•˜μ§€λ§Œ, λͺ©μ μ— λ”°λΌμ„œ λ””μžμΈ νŒ¨ν„΄μ—μ„œλŠ” λ‹€λ₯Έ νŒ¨ν„΄μœΌλ‘œ ꡬ뢄

λ°μ½”λ ˆμ΄ν„° νŒ¨ν„΄

  • 타깃에 뢀가적인 κΈ°λŠ₯을 λŸ°νƒ€μž„ μ‹œ λ‹€μ΄λ‚˜λ―Ήν•˜κ²Œ λΆ€μ—¬ν•΄μ£ΌκΈ° μœ„ν•΄ ν”„λ‘μ‹œλ₯Ό μ‚¬μš©ν•˜λŠ” νŒ¨ν„΄
    • λŸ°νƒ€μž„ μ‹œ λ‹€μ΄λ‚˜λ―Ή -> 컴파일 μ‹œμ , μ½”λ“œ μƒμ—μ„œλŠ” ν”„λ‘μ‹œμ™€ 타깃을 μ—°κ²°ν•˜μ—¬ μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” 뜻
  • ν”„λ‘μ‹œκ°€ λ”± ν•˜λ‚˜λ‘œ μ œν•œλ˜μ–΄ μžˆμ§€ μ•Šκ³ , ν”„λ‘μ‹œκ°€ 직접 타깃을 μ‚¬μš©ν•˜λ„λ‘ κ³ μ •μ‹œν‚¬ ν•„μš”λ„ μ—†λ‹€
  • 같은 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ νƒ€κ²Ÿκ³Ό μ—¬λŸ¬ 개의 ν”„λ‘μ‹œλ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€
일반적으둜 λ§ν•˜λŠ” ν”„λ‘μ‹œ vs λ””μžμΈ νŒ¨ν„΄μ—μ„œ λ§ν•˜λŠ” ν”„λ‘μ‹œ νŒ¨ν„΄
  1. ν΄λΌμ΄μ–ΈνŠΈμ™€ μ‚¬μš© λŒ€μƒ 사이에 λŒ€λ¦¬ 역할을 맑은 였브젝트λ₯Ό λ‘λŠ” 방법
  2. ν”„λ‘μ‹œλ₯Ό μ‚¬μš©ν•˜λŠ” 방법 μ€‘μ—μ„œ 타깃에 λŒ€ν•œ μ ‘κ·Ό 방법을 μ œμ–΄ν•˜λ €λŠ” λͺ©μ μ„ κ°€μ§„ 경우 πŸ“Œ
ν”„λ‘μ‹œ νŒ¨ν„΄μ€ νƒ€κΉƒμ˜ κΈ°λŠ₯ μžμ²΄μ—λŠ” κ΄€μ—¬ν•˜μ§€ μ•ŠμœΌλ©΄μ„œ μ ‘κ·Όν•˜λŠ” 방법을 μ œμ–΄ν•΄μ£ΌλŠ” ν”„λ‘μ‹œλ₯Ό μ΄μš©ν•˜λŠ” 것
  • λ‹€λ§Œ ν”„λ‘μ‹œλŠ” μ½”λ“œμ—μ„œ μžμ‹ μ΄ λ§Œλ“€κ±°λ‚˜ μ ‘κ·Όν•  타깃 클래슀 정보λ₯Ό ꡬ체적으둜 μ•Œκ³  μžˆλŠ” κ²½μš°κ°€ λ§Žλ‹€
    • ex) 생성 μ§€μ—° ν”„λ‘μ‹œμ˜ 경우, 타깃 클래슀의 ꡬ체적인 생성 방법을 μ•Œμ•„μ•Όν•¨

μ•žμœΌλ‘œμ˜ ν”„λ‘μ‹œμ˜ μ •μ˜

  1. 타깃과 λ™μΌν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„
  2. ν΄λΌμ΄μ–ΈνŠΈμ™€ 타깃 사이에 쑴재
  3. λΆ€κ°€ κΈ°λŠ₯ λ˜λŠ” μ ‘κ·Ό μ œμ–΄ κΈ°λŠ₯을 λ‹΄λ‹Ήν•˜λŠ” 였브젝트

λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œ

  • ν”„λ‘μ‹œ : κΈ°μ‘΄ μ½”λ“œμ— 영ν–₯을 μ£Όμ§€ μ•ŠμœΌλ©΄μ„œ νƒ€κΉƒμ˜ κΈ°λŠ₯을 ν™•μž₯ν•˜κ±°λ‚˜ μ ‘κ·Ό 방법을 μ œμ–΄ν•  수 μžˆλŠ” μœ μš©ν•œ 방법

    • μžλ°”μ˜ java.lang.reflect νŒ¨ν‚€μ§€ μ•ˆμ— ν”„λ‘μ‹œλ₯Ό μ†μ‰½κ²Œ λ§Œλ“€ 수 μžˆλ„λ‘ μ§€μ›ν•΄μ£ΌλŠ” ν΄λž˜μŠ€λ“€μ΄ μžˆλ‹€
  • ν”„λ‘μ‹œλ₯Ό λ§Œλ“€κΈ° 번거둜운 이유 두 κ°€μ§€
    1. μ›ν•˜λŠ” λΆ€κ°€ κΈ°λŠ₯을 μœ„ν•΄ ν•„μš”μ—†λŠ” λ©”μ†Œλ“œλ„ λͺ¨λ‘ κ΅¬ν˜„ν•΄μ•Όν•œλ‹€
    2. λΆ€κ°€ κΈ°λŠ₯ μ½”λ“œκ°€ 쀑볡될 κ°€λŠ₯성이 λ§Žλ‹€
  • λ¦¬ν”Œλž™μ…˜

    • λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œλŠ” λ¦¬ν”Œλž™μ…˜ κΈ°λŠ₯을 μ΄μš©ν•΄μ„œ ν”„λ‘μ‹œλ₯Ό λ§Œλ“€μ–΄ μ€€λ‹€

      @Test
      public void invokeMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
          String name = "Spring";
      
          // length()
          assertThat(name.length(), is(6));
      
          /**
          * Method ? λ¦¬ν”Œλ ‰μ…˜ API μ€‘μ—μ„œ λ©”μ†Œλ“œμ— λŒ€ν•œ μ •μ˜λ₯Ό 담은 μΈν„°νŽ˜μ΄μŠ€
          *          1. λ©”μ†Œλ“œμ— λŒ€ν•œ μžμ„Έν•œ 정보λ₯Ό λ‹΄κ³  있음
          *          2. νŠΉμ • 였브젝트의 λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰μ‹œν‚¬ 수 μžˆλ‹€
          *          -> invoke() λ©”μ†Œλ“œ μ‚¬μš©
          */
          Method lengthMethod = String.class.getMethod("length");
          assertThat((Integer)lengthMethod.invoke(name),
      	//                               invoke(λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰μ‹œν‚¬ 타깃 였브젝트)
                     									is(6));
      
          // charAt()
          assertThat(name.charAt(0), is('S'));
      
          Method charAtMethod = String.class.getMethod("charAt", int.class);
          assertThat((Character)charAtMethod.invoke(name, 0),
          //                                 invoke(λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰μ‹œν‚¬ 타깃 였브젝트, λ“€μ–΄κ°ˆ νŒŒλΌλ―Έν„°)
       										              is('S'));
      }
  • λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œ

    • ν”„λ‘μ‹œ νŒ©ν† λ¦¬μ— μ˜ν•΄ λŸ°νƒ€μž„ μ‹œ λ‹€μ΄λ‚˜λ―Ήν•˜κ²Œ λ§Œλ“€μ–΄μ§€λŠ” 였브젝트

    • λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œ μ˜€λΈŒμ νŠΈλŠ” νƒ€κΉƒμ˜ μΈν„°νŽ˜μ΄μŠ€μ™€ 같은 νƒ€μž…μœΌλ‘œ λ§Œλ“€μ–΄μ§„λ‹€

    • ν΄λΌμ΄μ–ΈνŠΈλŠ” λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œ 였브젝트λ₯Ό 타깃 μΈν„°νŽ˜μ΄μŠ€λ₯Ό 톡해 μ‚¬μš©ν•  수 μžˆλ‹€

      • ν”„λ‘μ‹œ νŒ©ν† λ¦¬μ—κ²Œ μΈν„°νŽ˜μ΄μŠ€ μ •λ³΄λ§Œ μ œκ³΅ν•΄μ£Όλ©΄ ν•΄λ‹Ή μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 클래슀의 였브젝트λ₯Ό μžλ™μœΌλ‘œ 생성
    • λΆ€κ°€κΈ°λŠ₯은 ν”„λ‘μ‹œ μ˜€λΈŒμ νŠΈμ™€ λ…λ¦½μ μœΌλ‘œ InvocationHandlerλ₯Ό κ΅¬ν˜„ν•œ μ˜€λΈŒμ νŠΈμ— λ‹΄λŠ”λ‹€ : λͺ¨λ“  μš”μ²­μ„ invoke() λ©”μ†Œλ“œλ‘œ 처리

    • 타깃 였브젝트 λ©”μ†Œλ“œ 호좜 + λΆ€κ°€ κΈ°λŠ₯ = κ²°κ³Ό 리턴 -> ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ 전달
      Object newProxyInstance(
          ClassLoader loader,
          // 1. λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œκ°€ μ •μ˜λ˜λŠ” 클래슀 λ‘œλ”λ₯Ό 제곡
      	Class<?>[] interfaces,
          // 2. ν”„λ‘μ‹œκ°€ κ΅¬ν˜„ν•΄μ•Ό ν•  μΈν„°νŽ˜μ΄μŠ€. ν•œ λ²ˆμ— ν•˜λ‚˜ μ΄μƒμ˜ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•  수 μžˆμœΌλ―€λ‘œ λ°°μ—΄ μ‚¬μš© 
      	InvocationHandler h
          // 3. λΆ€κ°€κΈ°λŠ₯ & μœ„μž„ μ½”λ“œλ₯Ό λ‹΄κ³  μžˆλŠ” InvocationHandler κ΅¬ν˜„ 였브젝트λ₯Ό 제곡
      );

λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œμ˜ ν™•μž₯

  • 리턴 νƒ€μž…μ€ Methodλ₯Ό μ΄μš©ν•œ 타깃 였브젝트의 λ©”μ†Œλ“œ 호좜 ν›„ λ¦¬ν„΄νƒ€μž…μ„ 확인해 νŠΉμ • κ²½μš°μ—λ§Œ λ°˜ν™˜
  • νƒ€κΉƒμ˜ μ’…λ₯˜μ— 상관없이 InvocationHandler 방식을 μ μš©ν•  수 μžˆλ‹€
  • 단, λ¦¬ν”Œλ ‰μ…˜ λ©”μ†Œλ“œμΈ Method.invoke()λ₯Ό μ΄μš©ν•΄ 타깃 였브젝트의 λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•  λ•ŒλŠ” 타깃 μ˜€λΈŒμ νŠΈμ—μ„œ λ°œμƒν•˜λŠ” μ˜ˆμ™Έκ°€ InvocationTargetException으둜 ν•œλ²ˆ 포μž₯λ˜μ–΄μ„œ μ „λ‹¬λœλ‹€
    • getTargetException() λ©”μ†Œλ“œλ‘œ μ€‘μ²©λ˜μ–΄ μžˆλŠ” μ˜ˆμ™Έλ₯Ό 가져와야 ν•œλ‹€

λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œλ₯Ό μœ„ν•œ νŒ©ν† λ¦¬ 빈

  • DI의 λŒ€μƒμ΄ λ˜λŠ” λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œ μ˜€λΈŒμ νŠΈλŠ” 일반적인 μŠ€ν”„λ§μ˜ 빈으둜 등둝할 방법이 μ—†λ‹€?
  • μŠ€ν”„λ§ λΉˆμ€ 기본적으둜 클래슀 이름과 ν”„λ‘œνΌν‹°λ‘œ μ •μ˜λ˜λ©°, μ§€μ •λœ 클래슀 이름을 κ°€μ§€κ³  λ¦¬ν”Œλ ‰μ…˜μ„ μ΄μš©ν•΄μ„œ ν•΄λ‹Ή 클래슀의 였브젝트λ₯Ό λ§Œλ“ λ‹€

    • Class의 newInstance() λ©”μ†Œλ“œ : ν•΄λ‹Ή 클래슀의 λ””ν΄νŠΈ μƒμ„±μžλ₯Ό ν˜ΈμΆœν•΄ 였브젝트 생성 ν›„ λ°˜ν™˜

      Date now = (Date) Class.forName("java.util.Date").newInstance();
  • λ‹€λ§Œ! λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œ μ˜€λΈŒμ νŠΈλŠ” Proxy 클래슀의 newProxyInstance() μŠ€νƒœν‹± νŒ©ν† λ¦¬ λ©”μ†Œλ“œλ₯Ό ν†΅ν•΄μ„œλ§Œ λ§Œλ“€ 수 μžˆλ‹€.

νŒ©ν† λ¦¬ 빈

  • 클래슀 정보λ₯Ό κ°€μ§€κ³  λ””ν΄νŠΈ μƒμ„±μžλ₯Ό 톡해 였브젝트λ₯Ό λ§Œλ“œλŠ” 방법 이외에 빈 생성 방법

  • μŠ€ν”„λ§μ„ λŒ€μ‹ ν•΄μ„œ 였브젝트의 μƒμ„±λ‘œμ§μ„ λ‹΄λ‹Ή

  • νŒ©ν† λ¦¬ λΉˆμ„ λ§Œλ“œλŠ” λŒ€ν‘œμ μΈ 방법
    • FactoryBean μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 클래슀λ₯Ό μŠ€ν”„λ§μ˜ 빈으둜 등둝
μŠ€ν”„λ§μ€ private μƒμ„±μžλ₯Ό κ°€μ§„ ν΄λž˜μŠ€λ„ 빈으둜 등둝해주면 λ¦¬ν”Œλ ‰μ…˜μ„ μ΄μš©ν•΄ 였브젝트λ₯Ό λ§Œλ“€ 수 μžˆλ‹€

But, μƒμ„±μžλ₯Ό private으둜 λ§Œλ“€μ—ˆλ‹€λŠ” 것은 μŠ€νƒœν‹± λ©”μ†Œλ“œλ₯Ό 톡해 였브젝트λ₯Ό λ§Œλ“€μ–΄μ•Ό ν•˜λŠ” μ΄μœ κ°€ 있기 λ•Œλ¬Έμ΄λ―€λ‘œ ꢌμž₯λ˜μ§€ μ•ŠλŠ”λ‹€.

  1. μŠ€ν”„λ§μ€ FactoryBean μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ ν΄λž˜μŠ€κ°€ 빈의 클래슀둜 μ§€μ •λ˜λ©΄
  2. νŒ©ν† λ¦¬ 빈 클래슀의 였브젝트의 getObject() λ©”μ†Œλ“œλ₯Ό μ΄μš©ν•΄ 였브젝트λ₯Ό κ°€μ Έμ˜€κ³ 
  3. 이λ₯Ό 빈 였브젝트둜 μ‚¬μš©ν•œλ‹€

ν”„λ‘μ‹œ νŒ©ν† λ¦¬ 빈 λ°©μ‹μ˜ μž₯점과 ν•œκ³„

  • μž₯점
    • ν”„λ‘μ‹œ νŒ©ν† λ¦¬ 빈의 μž¬μ‚¬μš©. μ½”λ“œμ˜ μˆ˜μ • 없이 λ‹€μ–‘ν•œ ν΄λž˜μŠ€μ— μ μš©ν•  수 μžˆλ‹€
  • ν•œκ³„μ 
    • ν•œ λ²ˆμ— μ—¬λŸ¬ 개의 ν΄λž˜μŠ€μ— 곡톡적인 λΆ€κ°€ κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” 것이 λΆˆκ°€λŠ₯ν•˜λ‹€
    • ν•˜λ‚˜μ˜ 타깃에 μ—¬λŸ¬ 개의 λΆ€κ°€κΈ°λŠ₯을 μ μš©ν•˜λ €λ©΄ λΆ€κ°€ κΈ°λŠ₯의 개수만큼 ν”„λ‘μ‹œ νŒ©ν† λ¦¬ 빈 섀정이 λΆ™μ–΄μ•Όν•œλ‹€
    • 타깃 μ˜€λΈŒμ νŠΈκ°€ λ‹¬λΌμ§ˆ λ•Œλ§ˆλ‹€ λ˜‘κ°™μ€ λΆ€κ°€κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” 였브젝트λ₯Ό μ€‘λ³΅μ μœΌλ‘œ λ§Œλ“€μ–΄μ•Όν•œλ‹€

6.4 μŠ€ν”„λ§μ˜ ν”„λ‘μ‹œ νŒ©ν† λ¦¬ 빈



🌱 Branch chapter06/refactor6.4에 μ‹€μŠ΅ 적용



μŠ€ν”„λ§μ€ μΌκ΄€λœ λ°©λ²•μœΌλ‘œ ν”„λ‘μ‹œλ₯Ό λ§Œλ“€ 수 있게 λ„μ™€μ£ΌλŠ” 좔상 λ ˆμ΄μ–΄λ₯Ό 제곡

μƒμ„±λœ ν”„λ‘μ‹œλŠ” μŠ€ν”„λ§μ˜ 빈으둜 λ“±λ‘λ˜μ–΄μ•Ό ν•˜κ³ , μŠ€ν”„λ§μ€ ν”„λ‘μ‹œ 였브젝트λ₯Ό μƒμ„±ν•΄μ£ΌλŠ” κΈ°μˆ μ„ μΆ”μƒν™”ν•œ νŒ©ν† λ¦¬ λΉˆμ„ 제곡

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

ν”„λ‘μ‹œλ₯Ό μƒμ„±ν•΄μ„œ 빈 였브젝트둜 λ“±λ‘ν•˜κ²Œ ν•΄μ£ΌλŠ” νŒ©ν† λ¦¬ 빈

μˆœμˆ˜ν•˜κ²Œ ν”„λ‘μ‹œλ₯Ό μƒμ„±ν•˜λŠ” μž‘μ—…λ§Œ λ‹΄λ‹Ή, ν”„λ‘μ‹œλ₯Ό 톡해 μ œκ³΅ν•΄μ€„ λΆ€κ°€ κΈ°λŠ₯은 λ³„λ„μ˜ λΉˆμ— 뢄리

TransactionHandler의 InvocationHandlerκ°€ μ•„λ‹Œ,

ProxyFactoryBean이 μƒμ„±ν•˜λŠ” ν”„λ‘μ‹œμ—μ„œ μ‚¬μš©ν•˜λŠ” λΆ€κ°€ κΈ°λŠ₯은 MethodInterceptor μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜μ—¬ λ§Œλ“ λ‹€

두 개의 차이점

  • InvocationHandler : invoke() λ©”μ†Œλ“œλŠ” 타깃 μ˜€λΈŒμ νŠΈμ— λŒ€ν•œ 정보λ₯Ό μ œκ³΅ν•˜μ§€ μ•ŠλŠ”λ‹€ -> 타깃 μ˜€λΈŒμ νŠΈμ— λŒ€ν•œ 정보λ₯Ό 직접 μ•Œκ³  μžˆμ–΄μ•Ό ν•œλ‹€

  • MethodInterceptor : invoke() λ©”μ†Œλ“œλŠ” ProxyFactoryBeanμœΌλ‘œλΆ€ν„° 타깃 였브젝트 정보λ₯Ό ν•¨κ»˜ μ œκ³΅λ°›λŠ”λ‹€

    β–Ά κ·Έ 덕뢄에 MethodInterceptorλŠ” 타깃 μ˜€λΈŒμ νŠΈμ— 상관없이 λ…λ¦½μ μœΌλ‘œ λ§Œλ“€μ–΄μ§ˆ 수 μžˆλ‹€

    β–Ά MethodInterceptor μ˜€λΈŒμ νŠΈλŠ” 타깃이 μ—¬λŸ¬ ν”„λ‘μ‹œμ—μ„œ ν•¨κ»˜ μ‚¬μš©ν•  수 있고, 싱글톀 빈으둜 등둝 κ°€λŠ₯ν•˜λ‹€

μ–΄λ“œλ°”μ΄μŠ€ : 타깃이 ν•„μš” μ—†λŠ” μˆœμˆ˜ν•œ λΆ€κ°€κΈ°λŠ₯

Advice : 타깃 μ˜€λΈŒμ νŠΈμ— μ μš©ν•˜λŠ” λΆ€κ°€κΈ°λŠ₯을 담은 였브젝튼

  • MethodInvocation은 μΌμ’…μ˜ 콜백 였브젝트둜 proceed() λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄ 타깃 였브젝트의 λ©”μ†Œλ“œλ₯Ό λ‚΄λΆ€μ μœΌλ‘œ μ‹€ν–‰ν•΄μ£ΌλŠ” κΈ°λŠ₯이 μžˆλ‹€

  • MethodInvocation κ΅¬ν˜„ 클래슀 : μΌμ’…μ˜ 곡유 κ°€λŠ₯ν•œ ν…œν”Œλ¦Ώμ²˜λŸΌ λ™μž‘

    • JDK의 λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œλ₯Ό 직접 μ‚¬μš©ν•˜λŠ” μ½”λ“œμ™€ κ°€μž₯ 큰 차이점
  • ProxyFactoryBean은 addAdvice()λ₯Ό μ΄μš©ν•΄ μ—¬λŸ¬ 개의 MethodInterceptorλ₯Ό μΆ”κ°€, μ—¬λŸ¬ λΆ€κ°€ κΈ°λŠ₯을 μ œκ³΅ν•΄μ£ΌλŠ” ν”„λ‘μ‹œλ₯Ό λ§Œλ“€ 수 μžˆλ‹€

  • addAdvice둜 MethodInterceptor μΆ”κ°€? β–Ά MethodInterceptorλŠ” Advice μΈν„°νŽ˜μ΄μŠ€λ₯Ό μƒμ†ν•˜κ³  μžˆλ‹€

  • ProxyFactoryBean은 κ΅¬ν˜„ν•΄μ•Ό ν•  μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ•Œλ €μ£Όμ§€ μ•Šμ•„λ„ 타깃 μ˜€λΈŒμ νŠΈκ°€ κ΅¬ν˜„ν•˜κ³  μžˆλŠ” μΈν„°νŽ˜μ΄μŠ€ 정보λ₯Ό μ•Œμ•„λ‚΄μ–΄ κ΅¬ν˜„ν•˜λŠ” ν”„λ‘μ‹œλ₯Ό λ§Œλ“ λ‹€


포인트컷 : λΆ€κ°€κΈ°λŠ₯ 적용 λŒ€μƒ λ©”μ†Œλ“œ μ„ μ • 방법

pointCut : λ©”μ†Œλ“œ μ„ μ • μ•Œκ³ λ¦¬μ¦˜μ„ 담은 였브젝트

  • MethodInterceptor μ˜€λΈŒμ νŠΈλŠ” μ—¬λŸ¬ ν”„λ‘μ‹œκ°€ κ³΅μœ ν•΄μ„œ μ‚¬μš©ν•  수 있으며, 타깃 정보λ₯Ό κ°€μ§€κ³  μžˆμ§€ μ•Šλ„λ‘ κ΅¬μ„±λ˜μ–΄ μžˆλ‹€. -> κ·Έλ ‡κΈ° λ•Œλ¬Έμ— μŠ€ν”„λ§ 싱글톀 빈으둜 등둝 κ°€λŠ₯ν•˜λ‹€
    • νŠΈλžœμž­μ…˜ 적용 λŒ€μƒ λ©”μ†Œλ“œ 이름 νŒ¨ν„΄μ„ λ„£μ–΄μ£ΌκΈ° κ³€λž€. νŒ¨ν„΄μ€ ν”„λ‘μ‹œλ§ˆλ‹€ λ‹€λ₯Ό 수 있으며 μ—¬λŸ¬ ν”„λ‘μ‹œκ°€ κ³΅μœ ν•˜λŠ” MethodInterceptor에 νŠΉμ • ν”„λ‘μ‹œ 적용 νŒ¨ν„΄μ„ 넣을 수 μ—†λ‹€
  • MethodInterceptorλŠ” ν”„λ‘μ‹œκ°€ ν΄λΌμ΄μ–ΈνŠΈλ‘œλΆ€ν„° λ°›λŠ” μš”μ²­μ„ 일일이 전달받을 ν•„μš” 없이, μž¬μ‚¬μš© κ°€λŠ₯ν•œ 순수 λΆ€κ°€κΈ°λŠ₯ 제곡 μ½”λ“œλ§Œ 남겨둔닀

μ–΄λ“œλ°”μ΄μ € = 포인트컷(λ©”μ†Œλ“œ μ„ μ • μ•Œκ³ λ¦¬μ¦˜) + μ–΄λ“œλ°”μ΄μŠ€(λΆ€κ°€κΈ°λŠ₯)


6.5 μŠ€ν”„λ§ AOP



🌱 Branch chapter06/refactor6.5에 μ‹€μŠ΅ 적용



☝ 아직 ν•΄κ²°ν•˜μ§€ λͺ»ν•œ 문제

  • λΆ€κ°€κΈ°λŠ₯의 적용이 ν•„μš”ν•œ 타깃 μ˜€λΈŒμ νŠΈλ§ˆλ‹€ 거의 λΉ„μŠ·ν•œ λ‚΄μš©μ˜ ProxyFactoryBean 빈 섀정정보λ₯Ό μΆ”κ°€ν•΄μ£ΌλŠ” 뢀뢄이 쀑볡됨

빈 ν›„μ²˜λ¦¬κΈ°λ₯Ό μ΄μš©ν•œ μžλ™ ν”„λ‘μ‹œ 생성기

μŠ€ν”„λ§μ€ μ»¨ν…Œμ΄λ„ˆλ‘œμ„œ μ œκ³΅ν•˜λŠ” κΈ°λŠ₯ μ€‘μ—μ„œ λ³€ν•˜μ§€ μ•ŠλŠ” 핡심적인 λΆ€λΆ„ μ™Έμ—λŠ” λŒ€λΆ€λΆ„ ν™•μž₯ν•  수 μžˆλ„λ‘ ν™•μž₯ 포인트λ₯Ό μ œκ³΅ν•΄μ€€λ‹€

▢️ BeanPostProcessor μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•΄μ„œ λ§Œλ“œλŠ” 빈 ν›„μ²˜λ¦¬κΈ°

* 빈 ν›„μ²˜λ¦¬κΈ° : 이름 κ·ΈλŒ€λ‘œ μŠ€ν”„λ§ 빈 였브젝트둜 λ§Œλ“€μ–΄μ§€κ³  λ‚œ 후에, 빈 였브젝트λ₯Ό λ‹€μ‹œ 가곡할 수 있게 ν•΄μ€Œ

* 빈 ν›„μ²˜λ¦¬κΈ°λ₯Ό μŠ€ν”„λ§μ— μ μš©ν•˜λŠ” 방법

  • 빈 ν›„μ²˜λ¦¬κΈ° 자체λ₯Ό 빈으둜 등둝



μŠ€ν”„λ§μ—μ„œ μ œκ³΅ν•˜λŠ” DefaultAdvisorAutoProxyCreator μžλ™ ν”„λ‘μ‹œ 생성기 μ‚¬μš©
  • μŠ€ν”„λ§μ€ 빈 ν›„μ²˜λ¦¬κΈ°κ°€ 빈으둜 λ“±λ‘λ˜μ–΄ 있으면 빈 μ˜€λΈŒμ νŠΈκ°€ 생성될 λ•Œλ§ˆλ‹€ 빈 ν›„μ²˜λ¦¬κΈ°μ— λ³΄λ‚΄μ„œ ν›„μ²˜λ¦¬ μž‘μ—… μš”μ²­

  • 빈 ν›„μ²˜λ¦¬κΈ°λ₯Ό μ΄μš©ν•œ μžλ™ ν”„λ‘μ‹œ 생성 방법
    • 빈으둜 λ“±λ‘λœ λͺ¨λ“  μ–΄λ“œλ°”μ΄μ € λ‚΄μ˜ ν¬μΈνŠΈμ»·μ„ μ΄μš©ν•΄ 전달받은 빈이 ν”„λ‘μ‹œ 적용 λŒ€μƒμΈμ§€ 확인
    • ν”„λ‘μ‹œ 적용 λŒ€μƒμ΄λΌλ©΄, λ‚΄μž₯된 ν”„λ‘μ‹œ μƒμ„±κΈ°μ—κ²Œ ν˜„μž¬ λΉˆμ— λŒ€ν•œ ν”„λ‘μ‹œλ₯Ό λ§Œλ“€κ²Œ ν•˜κ³ , λ§Œλ“€μ–΄μ§„ ν”„λ‘μ‹œμ— μ–΄λ“œλ°”μ΄μ €λ₯Ό μ—°κ²°
    • 빈 ν›„μ²˜λ¦¬κΈ°λŠ” ν”„λ‘μ‹œκ°€ μƒμ„±λ˜λ©΄ μ›λž˜ μ»¨ν…Œμ΄λ„ˆκ°€ 전달해쀀 빈 였브젝트 λŒ€μ‹  ν”„λ‘μ‹œ 였브젝트λ₯Ό μ»¨ν…Œμ΄λ„ˆμ—κ²Œ 돌렀쀌
    • μ»¨ν…Œμ΄λ„ˆλŠ” μ΅œμ’…μ μœΌλ‘œ 빈 ν›„μ²˜λ¦¬κΈ°κ°€ λŒλ €μ€€ 였브젝트(proxy)λ₯Ό 빈으둜 λ“±λ‘ν•˜κ³  μ‚¬μš©
  • μ΄λŸ¬ν•œ λΆ€κ°€κΈ°λŠ₯ μ μš©ν•  λΉˆμ„ μ„ μ •ν•˜λŠ” 둜직이 μΆ”κ°€λœ 포인트컷이 λ‹΄κΈ΄ μ–΄λ“œλ°”μ΄μ €λ₯Ό λ“±λ‘ν•˜κ³  빈 ν›„μ²˜λ¦¬κΈ° μ‚¬μš©ν•œλ‹€λ©΄, :golf: 일일이 ProxyFactoryBean λΉˆμ„ λ“±λ‘ν•˜μ§€ μ•Šμ•„λ„ 타깃 μ˜€λΈŒμ νŠΈμ— μžλ™μœΌλ‘œ ν”„λ‘μ‹œκ°€ 적용되게 ν•  수 μžˆλ‹€! 🌟


ν™•μž₯된 포인트컷

포인트 컷은 클래슀 필터와 λ©”μ†Œλ“œ 맀처 두가지λ₯Ό λŒλ €μ£ΌλŠ” λ©”μ†Œλ“œλ₯Ό κ°€μ§€κ³  μžˆλ‹€

  • getClassFilter() : ν”„λ‘μ‹œλ₯Ό μ μš©ν•  ν΄λž˜μŠ€μΈμ§€ 확인
  • getMethodMatcher() : μ–΄λ“œλ°”μ΄μŠ€λ₯Ό μ μš©ν•  λ©”μ†Œλ“œμΈμ§€ 확인

Pointcut μ„ μ • κΈ°λŠ₯을 λͺ¨λ‘ μ μš©ν•œλ‹€λ©΄?

λ¨Όμ € ν”„λ‘μ‹œλ₯Ό μ μš©ν•  ν΄λž˜μŠ€μΈμ§€ νŒλ‹¨ ν›„, 적용 λŒ€μƒ 클래슀의 경우 μ–΄λ“œλ°”μ΄μŠ€λ₯Ό μ μš©ν•  λ©”μ†Œλ“œμΈμ§€ 확인 ν›„ λ™μž‘


포인트컷 ν‘œν˜„μ‹μ„ μ΄μš©ν•œ 포인트컷

기쑴에 μ‚¬μš©ν–ˆλ˜ ν¬μΈνŠΈμ»·μ€ λ©”μ†Œλ“œ 이름 νŒ¨ν„΄, 클래슀 이름 νŒ¨ν„΄μ„ 각각 클래슀 필터와 λ©”μ†Œλ“œ 맀처 였브젝트둜 λΉ„κ΅ν•΄μ„œ μ„ μ •ν•˜λŠ” 방식

  • 클래슀 필터와 λ©”μ†Œλ“œ 맀처λ₯Ό κ΅¬ν˜„
  • μŠ€ν”„λ§μ΄ μ œκ³΅ν•˜λŠ” ν•„ν„°λ‚˜ 맀처 클래슀λ₯Ό 가져와 ν”„λ‘œνΌν‹° μ„€μ •
포인트컷 ν‘œν˜„μ‹ (pointcut expression)
  • μΌμ’…μ˜ ν‘œν˜„μ‹ μ–Έμ–΄λ₯Ό μ‚¬μš©ν•΄μ„œ ν¬μΈνŠΈμ»·μ„ μž‘μ„±ν•  수 μžˆλ„λ‘ ν•˜λŠ” 방법
  • AspectJExpressionPointcut : 포인트컷 ν‘œν˜„μ‹μ„ μ§€μ›ν•˜λŠ” 포인트컷
    • ν΄λž˜μŠ€μ™€ λ©”μ†Œλ“œμ˜ μ„ μ • μ•Œκ³ λ¦¬μ¦˜μ„ 포인트컷 ν‘œν˜„μ‹μ„ μ΄μš©ν•΄ ν•œ λ²ˆμ— μ§€μ •ν•  수 있게 ν•œλ‹€
포인트컷 ν‘œν˜„μ‹ 문법
  • AspectJ 포인트컷 ν‘œν˜„μ‹μ€ 포인트컷 μ§€μ‹œμžλ₯Ό μ΄μš©ν•΄ μž‘μ„±

  • 포인트컷 μ§€μ‹œμž λŒ€ν‘œμ  : execution() -> λ©”μ†Œλ“œλ₯Ό 싀행에 λŒ€ν•œ 포인트컷

    • execution() μ‚¬μš© ν‘œν˜„μ‹ 문법ꡬ쑰

      execution( [μ ‘κ·Όμ œν•œμžνŒ¨ν„΄] λ¦¬ν„΄νƒ€μž…νŒ¨ν„΄ [νŒ¨ν‚€μ§€&클래슀(μΈν„°νŽ˜μ΄μŠ€)μ΄λ¦„νŒ¨ν„΄.]λ©”μ†Œλ“œμ΄λ¦„νŒ¨ν„΄ (νŒŒλΌλ―Έν„°νŒ¨ν„΄ | .., ...))
      
  • bean() : μŠ€ν”„λ§μœΌλ‘œ μ‚¬μš©λ  λ•Œ 빈의 μ΄λ¦„μœΌλ‘œ 비ꡐ

    • ex) bean(*Service) : 아이디가 Service둜 λλ‚˜λŠ” λͺ¨λ“  빈 선택
  • @annotaion : νŠΉμ • μ–΄λ…Έν…Œμ΄μ…˜μ΄ νƒ€μž…, λ©”μ†Œλ“œ, νŒŒλΌλ―Έν„°μ— μ μš©λ˜μ–΄ μžˆλŠ” μƒνƒœλ₯Ό 보고 λ©”μ†Œλ“œ μ„ μ • 포인트컷

    • ex) @annotaion(org.springframework.transaction.annotation.Transactional)

AOP 적용 κ³Όμ •

  • νŠΈλžœμž­μ…˜ μ„œλΉ„μŠ€ 좔상화
    • λ°œμƒ 문제점 : νŠΉμ • νŠΈλžœμž­μ…˜ κΈ°μˆ μ— μ’…μ†λ˜λŠ” μ½”λ“œ
    • ν•΄κ²° : νŠΈλžœμž­μ…˜ μ μš©μ΄λΌλŠ” 좔상적인 μž‘μ—… λ‚΄μš©μ€ μœ μ§€ν•œ μ±„λ‘œ ꡬ체적인 κ΅¬ν˜„ 방법을 자유둭게 λ°”κΏ€μˆ˜ μžˆλ„λ‘ μ„œλΉ„μŠ€ 좔상화 기법 적용
    • μž₯점 : μΈν„°νŽ˜μ΄μŠ€μ™€ DIλ₯Ό 톡해 무엇을 ν•˜λŠ”μ§€λŠ” 남기고, 직접 κ΅¬ν˜„μ€ λΆ„λ¦¬ν•¨μœΌλ‘œμ¨ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 μ½”λ“œμ—λŠ” 영ν–₯을 μ£Όμ§€μ•Šκ³  λ…λ¦½μ μœΌλ‘œ λ³€κ²½ κ°€λŠ₯
  • ν”„λ‘μ‹œμ™€ λ°μ½”λ ˆμ΄μ…˜ νŒ¨ν„΄
    • λ°œμƒ 문제점 : νŠΈλžœμž­μ…˜ 적용 μ½”λ“œλ₯Ό λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 μ½”λ“œμ— λ…ΈμΆœμ‹œμΌœμ•Όν–ˆλ‹€
    • ν•΄κ²° : DIλ₯Ό μ΄μš©ν•΄ λ°μ½”λ ˆμ΄μ…˜ νŒ¨ν„΄μ„ 적용.ν΄λΌμ΄μ–ΈνŠΈκ°€ μΌμ’…μ˜ λŒ€λ¦¬μžμΈ ν”„λ‘μ‹œ 역할을 ν•˜λŠ” νŠΈλžœμž­μ…˜ λ°μ½”λ ˆμ΄ν„°λ₯Ό κ±°μ³μ„œ 타깃에 μ ‘κ·Ό κ°€λŠ₯
    • μž₯점 : λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 μ½”λ“œμ— 성격이 λ‹€λ₯Έ μ½”λ“œλ‘œλΆ€ν„° λ…λ¦½μ‹œν‚¬ 수 μžˆμ—ˆκ³  λ…λ¦½μ μœΌλ‘œ λ‘œμ§μ„ κ²€μ¦ν•˜λŠ” 고립된 λ‹¨μœ„ ν…ŒμŠ€νŠΈ 생성 κ°€λŠ₯
  • λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œμ™€ ν”„λ‘μ‹œ νŒ©ν† λ¦¬ 빈
    • λ°œμƒ 문제점 : λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 μΈν„°νŽ˜μ΄μŠ€μ˜ λͺ¨λ“  λ©”μ†Œλ“œλ§ˆλ‹€ νŠΈλžœμž­μ…˜ κΈ°λŠ₯을 λΆ€μ—¬ν•˜λŠ” μ½”λ“œλ₯Ό λ„£μ–΄ ν”„λ‘μ‹œν΄λž˜μŠ€λ₯Ό λ§Œλ“œλŠ” μž‘μ—…μ΄ λ²ˆκ±°λ‘œμ›€
    • ν•΄κ²° : JDK λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œ 기술 적용 -> μŠ€ν”„λ§ ν”„λ‘μ‹œ νŒ©ν† λ¦¬ λΉˆμ„ μ΄μš©ν•΄ λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œ 생성 방법에 DI λ„μž…
    • μž₯점 : λ‚΄λΆ€μ μœΌλ‘œ ν…œν”Œλ¦Ώ/콜백 νŒ¨ν„΄μ„ ν™œμš©ν•˜λŠ” μŠ€ν”„λ§μ˜ ν”„λ‘μ‹œ 빈 덕뢄에 λΆ€κ°€κΈ°λŠ₯을 담은 μ–΄λ“œλ°”μ΄μŠ€μ™€ λΆ€κ°€κΈ°λŠ₯ μ„ μ • μ•Œκ³ λ¦¬μ¦˜μ„ 담은 ν¬μΈνŠΈκ²ƒμ€ ν”„λ‘μ‹œμ—μ„œ 뢄리 κ°€λŠ₯. μ—¬λŸ¬ ν”„λ‘μ‹œκ°€ κ³΅μœ ν•΄μ„œ μ‚¬μš© κ°€λŠ₯
  • μžλ™ ν”„λ‘μ‹œ 생성 방법과 포인트컷
    • λ°œμƒ 문제점 : νŠΈλžœμž­μ…˜ 적용 λŒ€μƒμ΄ λ˜λŠ” λΉˆλ§ˆλ‹€ 일일이 ν”„λ‘μ‹œ νŒ©ν† λ¦¬ λΉˆμ„ μ„€μ •ν•΄μ€˜μ•Ό ν•˜λŠ” λ²ˆκ±°λ‘œμ›€
    • ν•΄κ²° : μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ˜ 빈 생성 ν›„μ²˜λ¦¬ 기법을 ν™œμš©ν•΄ μ»¨ν…Œμ΄λ„ˆ μ΄ˆκΈ°ν™” μ‹œμ μ—μ„œ μžλ™μœΌλ‘œ ν”„λ‘μ‹œλ₯Ό λ§Œλ“€μ–΄μ£ΌλŠ” 방법 λ„μž…. 클래슀λ₯Ό μ„ μ •ν•˜λŠ” κΈ°λŠ₯을 담은 ν™•μž₯된 포인트컷 μ‚¬μš©
    • μž₯점 : λΆ€κ°€ κΈ°λŠ₯을 어디에 μ μš©ν•˜λŠ”μ§€μ— λŒ€ν•œ 정보λ₯Ό ν¬μΈνŠΈμ»·μ΄λΌλŠ” 독립적인 μ •λ³΄λ‘œ μ™„μ „νžˆ 뢄리

AOP : μ• μŠ€νŽ™νŠΈ μ§€ν–₯ ν”„λ‘œκ·Έλž˜λ°

μ• μŠ€νŽ™νŠΈ aspect
  • κ·Έ 자체둜 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 핡심기λŠ₯을 λ‹΄κ³  μžˆμ§€λŠ” μ•Šμ§€λ§Œ, μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ΅¬μ„±ν•˜λŠ” μ€‘μš”ν•œ ν•œ κ°€μ§€ μš”μ†Œμ΄κ³ , 핡심 κΈ°λŠ₯에 λΆ€κ°€λ˜μ–΄ 의미λ₯Ό κ°–λŠ” νŠΉλ³„ν•œ λͺ¨λ“ˆ
  • 뢀가될 κΈ°λŠ₯을 μ •μ˜ν•œ μ½”λ“œμΈ μ–΄λ“œλ°”μ΄μŠ€ + 어디에 μ μš©ν• μ§€λ₯Ό κ²°μ •ν•˜λŠ” 포인트컷
μ• μŠ€νŽ™νŠΈ μ§€ν–₯ ν”„λ‘œκ·Έλž˜λ° Aspect Oriented Programming
  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 핡심기λŠ₯μ—μ„œ λΆ€κ°€κΈ°λŠ₯을 λΆ„λ¦¬ν•΄μ„œ μ• μŠ€νŽ™νŠΈλΌλŠ” λ…νŠΉν•œ λͺ¨λ“ˆλ‘œμ„œ μ„€κ³„ν•˜κ³  κ°œλ°œν•˜λŠ” 방법

  • μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ νŠΉμ •ν•œ 관점을 κΈ°μ€€μœΌλ‘œ 바라볼 수 있게 ν•΄μ€€λ‹€λŠ” 의미


AOP 적용 기술

μŠ€ν”„λ§μ€ λ‹€μ–‘ν•œ κΈ°μˆ μ„ μ‘°ν•©ν•΄ AOPλ₯Ό μ§€μ›ν•˜κ³  μžˆλ‹€. κ·Έ 쀑 κ°€μž₯ 핡심은 ν”„λ‘μ‹œ 이용 -> ν”„λ‘μ‹œλ‘œ λ§Œλ“€μ–΄μ„œ DI둜 μ—°κ²°λœ 빈 사이에 μ μš©ν•΄ νƒ€κΉƒμ˜ λ©”μ†Œλ“œ 호좜 과정에 μ°Έμ—¬ν•΄μ„œ λΆ€κ°€ κΈ°λŠ₯을 μ œκ³΅ν•΄μ£Όλ„λ‘ λ§Œλ“¦

μŠ€ν”„λ§ AOP의 λΆ€κ°€κΈ°λŠ₯을 담은 μ–΄λ“œλ°”μ΄μŠ€κ°€ μ μš©λ˜λŠ” λŒ€μƒμ€ 였브젝트의 λ©”μ†Œλ“œ. ν”„λ‘μ‹œ 방식을 μ‚¬μš©ν–ˆκΈ° λ•Œλ¬Έμ— λ©”μ†Œλ“œ 호좜 과정에 μ°Έμ—¬ν•΄μ„œ λΆ€κ°€ κΈ°λŠ₯을 μ œκ³΅ν•΄μ£Όκ²Œ λ˜μ–΄ μžˆλ‹€.

μ–΄λ“œλ°”μ΄μŠ€κ°€ κ΅¬ν˜„ν•˜λŠ” MethodInterceptor μΈν„°νŽ˜μ΄μŠ€λŠ” λ‹€μ΄λ‚˜λ―Ή ν”„λ‘μ‹œμ˜ InvocationHandler와 λ§ˆμ°¬κ°€μ§€λ‘œ ν”„λ‘μ‹œλ‘œλΆ€ν„° λ©”μ†Œλ“œ μš”μ²­ 정보λ₯Ό μ „λ‹¬λ°›μ•„μ„œ 타깃 였브젝트의 λ©”μ†Œλ“œλ₯Ό 호좜.ν˜ΈμΆœν•˜λŠ” 전후에 λ‹€μ–‘ν•œ λΆ€κ°€κΈ°λŠ₯ 제곡

ν”„λ‘μ‹œ : λ…λ¦½μ μœΌλ‘œ κ°œλ°œν•œ λΆ€κ°€κΈ°λŠ₯ λͺ¨λ“ˆμ„ λ‹€μ–‘ν•œ 타깃 였브젝트의 λ©”μ†Œλ“œμ— λ‹€μ΄λ‚˜λ―Ήν•˜κ²Œ μ μš©ν•˜κΈ° μœ„ν•΄ κ°€μž₯ μ€‘μš”ν•œ μ—­ν• 

μŠ€ν”„λ§ AOPλŠ” ν”„λ‘μ‹œ λ°©μ‹μ˜ AOP라고 ν•  수 μžˆλ‹€


ν”„λ‘μ‹œλ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” AOP : AspectJ
  • AspectJλŠ” ν”„λ‘μ‹œλ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” λŒ€ν‘œμ μΈ AOP 기술

  • 타깃 였브젝트λ₯Ό λœ―μ–΄κ³ μ³μ„œ λΆ€κ°€κΈ°λŠ₯을 직접 λ„£μ–΄μ£ΌλŠ” 방법 μ‚¬μš©

  • 컴파일된 νƒ€κΉƒμ˜ 클래슀 파일 자체λ₯Ό μˆ˜μ •ν•˜κ±°λ‚˜ ν΄λž˜μŠ€κ°€ JVM에 λ‘œλ”©λ˜λŠ” μ‹œμ μ„ κ°€λ‘œμ±„μ„œ λ°”μ΄νŠΈμ½”λ“œλ₯Ό μ‘°μž‘ν•˜λŠ” 방법 μ‚¬μš©

  • AspectJκ°€ 컴파일된 클래슀 파일 μˆ˜μ •/λ°”μ΄νŠΈμ½”λ“œ μ‘°μž‘κ°™μ€ 방법을 μ‚¬μš©ν•˜λŠ” 이유
    • λ°”μ΄νŠΈμ½”λ“œλ₯Ό μ‘°μž‘ν•΄μ„œ 타깃 였브젝트λ₯Ό 직접 μˆ˜μ •ν•΄λ²„λ¦¬λ©΄ DI μ»¨ν…Œμ΄λ„ˆμ˜ 도움을 λ°›μ•„μ„œ μžλ™ ν”„λ‘μ‹œ 생성방식을 μ‚¬μš©ν•˜μ§€ μ•Šκ³  AOP 적용 κ°€λŠ₯
    • ν”„λ‘μ‹œ 방식보닀 훨씬 κ°•λ ₯ν•˜κ³  μœ μ—°ν•œ AOP κ°€λŠ₯
      • ν”„λ‘μ‹œ AOPλ₯Ό μ μš©ν•  λ•Œ : λΆ€κ°€κΈ°λŠ₯을 λΆ€μ—¬ν•  λŒ€μƒμ€ ν΄λΌμ΄μ–ΈνŠΈκ°€ 직접 ν˜ΈμΆœν•  λ•Œ μ‚¬μš©ν•˜λŠ” λ©”μ†Œλ“œλ‘œ μ œν•œ
      • λ°”μ΄νŠΈμ½”λ“œλ₯Ό 직접 μ‘°μž‘ν•΄μ„œ AOPλ₯Ό μ μš©ν•  λ•Œ : 였브젝트의 생성, ν•„λ“œ κ°’μ˜ μ‘°νšŒμ™€ μ‘°μž‘, μŠ€νƒœν‹± μ΄ˆκΈ°ν™” λ“± λ‹€μ–‘ν•œ μž‘μ—…μ„ λΆ€κ°€κΈ°λŠ₯에 λΆ€μ—¬ κ°€λŠ₯

AOP μš©μ–΄ 정리
타깃

λΆ€κ°€κΈ°λŠ₯을 λΆ€μ—¬ν•  λŒ€μƒ

핡심기λŠ₯을 담은 클래슀일 수 μžˆμ§€λ§Œ κ²½μš°μ— 따라 λ‹€λ₯Έ λΆ€κ°€κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” ν”„λ‘μ‹œ 였브젝트일 수 μžˆλ‹€


μ–΄λ“œλ°”μ΄μŠ€

νƒ€κΉƒμ—κ²Œ μ œκ³΅ν•  λΆ€κ°€κΈ°λŠ₯을 담은 λͺ¨λ“ˆ

였브젝트둜 μ •μ˜ν•˜κΈ°λ„ ν•˜μ§€λ§Œ λ©”μ†Œλ“œ λ ˆλ²¨μ—μ„œ μ •μ˜ν•  μˆ˜λ„ μžˆλ‹€


쑰인포인트

μ–΄λ“œλ°”μ΄μŠ€κ°€ 적용될 수 μžˆλŠ” μœ„μΉ˜

μŠ€ν”„λ§μ˜ ν”„λ‘μ‹œ AOPμ—μ„œ 쑰인 ν¬μΈνŠΈλŠ” λ©”μ†Œλ“œμ˜ μ‹€ν–‰ 단계 뿐


포인트컷

μ–΄λ“œλ°”μ΄μŠ€λ₯Ό μ μš©ν•  쑰인 포인트λ₯Ό μ„ λ³„ν•˜λŠ” μž‘μ—… λ˜λŠ” κ·Έ κΈ°λŠ₯을 μ •μ˜ν•œ λͺ¨λ“ˆ

μŠ€ν”„λ§μ˜ 쑰인 ν¬μΈνŠΈλŠ” λ©”μ†Œλ“œμ˜ μ‹€ν–‰μ΄λ―€λ‘œ μŠ€ν”„λ§μ˜ ν¬μΈνŠΈμ»·μ€ λ©”μ†Œλ“œλ₯Ό μ„ μ •ν•˜λŠ” κΈ°λŠ₯을 κ°–κ³  μžˆλ‹€


ν”„λ‘μ‹œ

ν΄λΌμ΄μ–ΈνŠΈμ™€ 타깃 사이에 투λͺ…ν•˜κ²Œμ‘΄μž¬ν•˜λ©΄μ„œ λΆ€κ°€κΈ°λŠ₯을 μ œκ³΅ν•˜λŠ” 였브젝트

DIλ₯Ό 톡해 타깃 λŒ€μ‹  ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ μ£Όμž…λ˜λ©°, ν΄λΌμ΄μ–ΈνŠΈμ˜ λ©”μ†Œλ“œ ν˜ΈμΆœμ„ λŒ€μ‹  λ°›μ•„μ„œ 타깃에 μœ„μž„ν•΄μ£Όλ©΄μ„œ, κ·Έ 과정에 λΆ€κ°€κΈ°λŠ₯을 λΆ€μ—¬


μ–΄λ“œλ°”μ΄μ €

포인트컷과 μ–΄λ“œλ°”μ΄μŠ€λ₯Ό ν•˜λ‚˜μ”© κ°–κ³  μžˆλŠ” 였브젝트

μŠ€ν”„λ§ AOPμ—λ§Œ νŠΉλ³„ν•˜κ²Œ μ‚¬μš©λ˜λŠ” μš©μ–΄


μ• μŠ€νŽ™νŠΈ

AOP의 κΈ°λ³Έ λͺ¨λ“ˆ

ν•œ 개 λ˜λŠ” κ·Έ μ΄μƒμ˜ 포인트컷과 μ–΄λ“œλ°”μ΄μŠ€μ˜ μ‘°ν•©μœΌλ‘œ λ§Œλ“€μ–΄μ§€λ©° 보톡 싱글톀 ν˜•νƒœμ˜ 였브젝트둜 쑴재


μŠ€ν”„λ§ AOPλ₯Ό μ μš©ν•˜κΈ° μœ„ν•΄ μΆ”κ°€ν–ˆλ˜ 빈(ex. μ–΄λ“œλ°”μ΄μ €, 포인트컷, μžλ™ ν”„λ‘μ‹œ etc..)듀은 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ μœ„ν•œ λΉˆκ³ΌλŠ” 성격이 λ‹€λ₯΄λ‹€.

μ΄λŸ¬ν•œ λΉˆλ“€μ„ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— μ˜ν•΄ μžλ™ μΈμ‹λ˜μ„œ νŠΉλ³„ν•œ μž‘μ—…μ„ μœ„ν•΄ μ‚¬μš©λ¨

μŠ€ν”„λ§μ˜ ν”„λ‘μ‹œ 방식 AOPλ₯Ό μ μš©ν•˜κΈ° μœ„ν•΄ μ΅œμ†Œν•œμœΌλ‘œ 등둝할 빈 4개
  • μžλ™ ν”„λ‘μ‹œ 생성기
    • μŠ€ν”„λ§μ˜ DefaultAdvisorAutoProxyCreator 클래슀λ₯Ό 빈으둜 등둝
    • μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ»¨ν…μŠ€νŠΈκ°€ 빈 였브젝트λ₯Ό μƒμ„±ν•˜λŠ” 과정에 빈 ν›„μ²˜λ¦¬κΈ°λ‘œ μ°Έμ—¬
    • 빈으둜 λ“±λ‘λœ μ–΄λ“œλ°”μ΄μ €λ₯Ό μ΄μš©ν•΄μ„œ ν”„λ‘μ‹œλ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•˜λŠ” κΈ°λŠ₯ λ‹΄λ‹Ή
  • μ–΄λ“œλ°”μ΄μŠ€
    • λΆ€κ°€κΈ°λŠ₯을 κ΅¬ν˜„ν•œ 클래슀λ₯Ό 빈으둜 등둝
  • 포인트컷
    • μŠ€ν”„λ§μ˜ AspectJExpressionPointcut을 빈으둜 λ“±λ‘ν•΄μ„œ μ‚¬μš©
    • μ–΄λ“œλ°”μ΄μŠ€μ™€ ν¬μΈνŠΈμ»·μ„ ν”„λ‘œνΌν‹°λ‘œ μ°Έμ‘°ν•˜λŠ” 것 μ™Έμ—λŠ” κΈ°λŠ₯이 μ—†λ‹€

6.6 νŠΈλžœμž­μ…˜ 속성



🌱 Branch chapter06/refactor6.6에 μ‹€μŠ΅ 적용



πŸ’‘ νŠΈλžœμž­μ…˜ λ§€λ‹ˆμ €λ₯Ό 톡해 νŠΈλžœμž­μ…˜μ„ μ‹œμž‘ν• λ €κ³  ν•  λ•Œ getTransaction()μ΄λΌλŠ” λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•΄ DefaultTransactionDefinitionλ₯Ό λ°›μ•„μ˜€λŠ” μ΄μœ λŠ” λ¬΄μ—‡μΌκΉŒ


TransactionDefinition의 νŠΈλžœμž­μ…˜μ˜ λ™μž‘λ°©μ‹μ— 영ν–₯을 쀄 수 μžˆλŠ” λ„€ κ°€μ§€ 속성


1. νŠΈλžœμž­μ…˜ μ „νŒŒ (transaction propagation)

νŠΈλžœμž­μ…˜μ˜ κ²½κ³„μ—μ„œ 이미 진행쀑인 νŠΈλžœμž­μ…˜μ΄ μžˆμ„ λ•Œ λ˜λŠ” 없을 λ•Œ μ–΄λ–»κ²Œ λ™μž‘ν•  것인가λ₯Ό κ²°μ •ν•˜λŠ” 방식

νŠΈλžœμž­μ…˜ μ „νŒŒ 속성 μ’…λ₯˜
  • PROPAGATION_REQUIRED
    • κ°€μž₯ 많이 μ‚¬μš©λ˜λŠ” νŠΈλžœμž­μ…˜ μ „νŒŒ 속성
    • μ§„ν–‰ 쀑인 νŠΈλžœμž­μ…˜μ΄ μ—†μœΌλ©΄ μƒˆλ‘œ μ‹œμž‘ν•˜κ³ , 이미 μ‹œμž‘λœ νŠΈλžœμž­μ…˜μ΄ 있으면 이에 μ°Έμ—¬
    • A, B, A->B, B->A λ„€ κ°€μ§€μ˜ μ‘°ν•© νŠΈλžœμž­μ…˜μ΄ κ°€λŠ₯
    • DefaultTransactionDefinition의 νŠΈλžœμž­μ…˜ μ „νŒŒ 속성
  • PROPAGATION_REQUIRES_NEW
    • 항상 μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜μ„ μ‹œμž‘ (독립적인 νŠΈλžœμž­μ…˜μ„ 보μž₯ν•  λ•Œ μ‚¬μš©)
    • μ•žμ—μ„œ μ‹œμž‘λœ νŠΈλžœμž­μ…˜μ΄ μžˆλ“  μ—†λ“  상관없이 μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜μ„ λ§Œλ“€μ–΄μ„œ λ…μžμ μœΌλ‘œ λ™μž‘ν•˜κ²Œ 함
  • PROPAGATION_NOT_SUPPORTED
    • νŠΈλžœμž­μ…˜ 없이 λ™μž‘ν•˜λ„λ‘ λ§Œλ“€κ³ , μ§„ν–‰ 쀑인 νŠΈλžœμž­μ…˜μ΄ μžˆμ–΄λ„ λ¬΄μ‹œ

    • νŠΈλžœμž­μ…˜μ„ λ¬΄μ‹œν•˜λŠ” 속성을 λ‘λŠ” 이유?
      • ν•œκΊΌλ²ˆμ— μ μš©λ˜λŠ” λ§Žμ€ λ©”μ†Œλ“œ 쀑에 νŠΉμ • λ©”μ†Œλ“œλ§Œ νŠΈλžœμž­μ…˜ μ μš©μ—μ„œ μ œμ™Έν•˜λ €λ©΄, 포인트컷이 μƒλ‹Ήνžˆ λ³΅μž‘ν•΄μ§ˆ 수 μžˆλ‹€. νŠΉμ • λ©”μ†Œλ“œλ₯Ό μ œμ™Έμ‹œν‚¬ λ•Œ μ‚¬μš©ν•˜λŠ” 속성

❗ νŠΈλžœμž­μ…˜ λ§€λ‹ˆμ €λ₯Ό 톡해 νŠΈλžœμž­μ…˜μ„ μ‹œμž‘ν• λ €κ³  ν•  λ•Œ getTransaction()μ΄λΌλŠ” λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” μ΄μœ λŠ” νŠΈλžœμž­μ…˜ μ „νŒŒ 속성이 있기 λ•Œλ¬Έ


2. κ²©λ¦¬μˆ˜μ€€ isolation level
  • λͺ¨λ“  DB νŠΈλžœμž­μ…˜μ€ κ²©λ¦¬μˆ˜μ€€μ„ κ°€μ§€κ³  μžˆμ–΄μ•Ό ν•œλ‹€

  • μ μ ˆν•˜κ²Œ κ²©λ¦¬μˆ˜μ€€μ„ μ‘°μ •ν•΄μ„œ κ°€λŠ₯ν•œ ν•œ λ§Žμ€ νŠΈλžœμž­μ…˜μ„ λ™μ‹œμ— μ§„ν–‰μ‹œν‚€λ©΄μ„œλ„ λ¬Έμ œκ°€ λ°œμƒν•˜μ§€ μ•Šκ²Œ ν•˜λŠ” μ œμ–΄κ°€ ν•„μš”

  • DefaultTransactionDefinition은 기본적으둜 ISOLATION_DEFAULT 둜 격리 μˆ˜μ€€μ΄ μ„€μ •λ˜μ–΄μžˆκ³ , νŠΉλ³„ν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” λ©”μ†Œλ“œμ˜ κ²½μš°μ—λŠ” 격리 μˆ˜μ€€μ„ μ§€μ •ν•  ν•„μš”κ°€ μžˆλ‹€


3. μ œν•œμ‹œκ°„ timeout
  • νŠΈλžœμž­μ…˜μ„ μˆ˜ν–‰ν•˜λŠ” μ œν•œμ‹œκ°„ μ„€μ • κ°€λŠ₯
  • DefaultTransactionDefinition의 κΈ°λ³Έ 섀정은 μ œν•œμ‹œκ°„ μ—†μŒ
  • μƒˆλ‘œμš΄ νŠΈλžœμž­μ…˜μ„ μ‹œμž‘ν•˜λŠ” PROPAGATION_REQUIRES_NEW, PROPAGATION_NOT_SUPPORTED와 ν•¨κ»˜ μ‚¬μš©ν•΄μ•Ό 의미 있음

4. μ½κΈ°μ „μš© read only
  • νŠΈλžœμž­μ…˜ λ‚΄μ—μ„œ 데이터λ₯Ό μ‘°μž‘ν•˜λŠ” μ‹œλ„λ₯Ό 막아쀄 수 μžˆλ‹€
  • 데이터 μ•‘μ„ΈμŠ€ κΈ°μˆ μ— λ”°λΌμ„œ μ„±λŠ₯이 ν–₯상될 수 μžˆλ‹€

νŠΈλžœμž­μ…˜ 인터셉터와 νŠΈλžœμž­μ…˜ 속성

λ©”μ†Œλ“œλ³„λ‘œ λ‹€λ₯Έ νŠΈλžœμž­μ…˜ μ •μ˜λ₯Ό μ μš©ν•˜λ €λ©΄ μ–΄λ“œλ°”μ΄μŠ€μ˜ κΈ°λŠ₯을 ν™•μž₯ν•΄μ•Όν•œλ‹€

μŠ€ν”„λ§μ—λŠ” νŽΈλ¦¬ν•˜κ²Œ νŠΈλžœμž­μ…˜ 경계섀정 μ–΄λ“œλ°”μ΄μŠ€λ‘œ μ‚¬μš©ν•  수 μžˆλ„λ‘ λ§Œλ“€μ–΄μ§„ TransactionInterceptorκ°€ 쑴재

TransactionInterceptor의 λ™μž‘ 방식 = 기쑴의 TransactionAdvice + νŠΈλžœμž­μ…˜ μ •μ˜λ₯Ό λ©”μ†Œλ“œ 이름 νŒ¨ν„΄μ„ μ΄μš©ν•΄ μ§€μ • κ°€λŠ₯

TransactionInterceptor의 두 κ°€μ§€ ν”„λ‘œνΌν‹°
  • PlatformTransactionManager
  • Properties νƒ€μž… transactionAttributes : νŠΈλžœμž­μ…˜ 속성을 μ •μ˜ν•œ ν”„λ‘œνΌν‹°
    • TransactionDefinition λ„€ κ°€μ§€ κΈ°λ³Έ ν•­λͺ© + rollbackOn()
    • * rollbackOn() : μ–΄λ–€ μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ©΄ 둀백을 ν•  것인가 κ²°μ •ν•˜λŠ” λ©”μ†Œλ“œ
TransactionInterceptor의 두 κ°€μ§€ μ˜ˆμ™Έ 처리 방식
  • λŸ°νƒ€μž„ μ˜ˆμ™Έ λ°œμƒ μ‹œ, νŠΈλžœμž­μ…˜ λ‘€λ°±
  • 체크 μ˜ˆμ™Έκ°€ λ°œμƒν•  경우, μ˜ˆμ™Έμƒν™©μœΌλ‘œ ν•΄μ„ν•˜μ§€ μ•Šκ³  μΌμ’…μ˜ λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ— λ”°λ₯Έ 의미 μžˆλŠ” 리턴 λ°©μ‹μ˜ ν•œ κ°€μ§€λ‘œ 인식해 νŠΈλžœμž­μ…˜ 컀밋
TransactionInterceptor의 μ˜ˆμ™Έ 처리 κΈ°λ³Έ 원칙을 λ”°λ₯΄μ§€ μ•ŠλŠ” 경우
  • rollbackOn() 속성을 둬 기본원칙과 νŠΉμ • μ˜ˆμ™Έμ— 따라 μ»€μŠ€ν…€ κ°€λŠ₯

6.7 μ–΄λ…Έν…Œμ΄μ…˜ νŠΈλžœμž­μ…˜ 속성과 포인트컷


@Transaction μ–΄λ…Έν…Œμ΄μ…˜

  • 직접 타깃에 νŠΈλžœμž­μ…˜ 속성 정보λ₯Ό κ°€μ§„ μ–΄λ…Έν…Œμ΄μ…˜ μ§€μ •
  • @Transaction의 타깃 : λ©”μ†Œλ“œ & νƒ€μž…
  • @Transaction을 νŠΈλžœμž­μ…˜ 속성 μ •λ³΄λ‘œ μ‚¬μš©ν•  λ•Œ ? : @Transactionκ°€ λΆ€μ—¬λœ λͺ¨λ“  였브젝트λ₯Ό μžλ™μœΌλ‘œ 타깃 였브젝트둜 인식 -> TransactionAttributeSourcePointcut 포인트컷 μ‚¬μš©
  • λ©”μ†Œλ“œλ§ˆλ‹€ λ‹€λ₯΄κ²Œ μ„€μ •ν•  μˆ˜λ„ μžˆλ‹€

λŒ€μ²΄ μ •μ±… (fallback)

@Transaction νŠΈλžœμž­μ…˜ λΆ€κ°€κΈ°λŠ₯ 적용 λ‹¨μœ„λŠ” λ©”μ†Œλ“œμ΄λ©°, μœ μ—°ν•œ 속성 μ œμ–΄κ°€ κ°€λŠ₯

But, λ™μΌν•œ 속성 정보λ₯Ό κ°€μ§„ μ–΄λ…Έν…Œμ΄μ…˜μ„ 반볡적으둜 λ©”μ†Œλ“œλ§ˆλ‹€ λΆ€μ—¬ν•˜λ©΄ μ½”λ“œκ°€ μ§€μ €λΆ„ν•΄μ§€κ³  μ‹€μˆ˜ 유발

▢️ @Transaction을 μ μš©ν•  λ•Œ 4단계 λŒ€μ²΄ μ •μ±…

  1. 타깃 λ©”μ†Œλ“œ : κ΅¬ν˜„ λ©”μ†Œλ“œ
  2. **타깃 클래슀 **: κ΅¬ν˜„ 클래슀 λ‚΄ λͺ¨λ“  λ©”μ†Œλ“œ
  3. μ„ μ–Έ λ©”μ†Œλ“œ : μΈν„°νŽ˜μ΄μŠ€ λ©”μ†Œλ“œ
  4. μ„ μ–Έ νƒ€μž… : μΈν„°νŽ˜μ΄μŠ€ νƒ€μž… λ‚΄ λͺ¨λ“  λ©”μ†Œλ“œ

4단계 μˆœμ„œλŒ€λ‘œ @Transaction이 μ μš©λλŠ”μ§€ ν™•μΈν•˜κ³  κ°€μž₯ λ¨Όμ € 발견된 속성정보 μ‚¬μš©

λκΉŒμ§€ λ°œκ²¬λ˜μ§€ μ•ŠμœΌλ©΄ ν•΄λ‹Ή λ©”μ†Œλ“œλŠ” νŠΈλžœμž­μ…˜ μ μš©λŒ€μƒ X


6.8 νŠΈλžœμž­μ…˜ 지원 ν…ŒμŠ€νŠΈ


선언적 νŠΈλžœμž­μ…˜ declarative transaction
  • AOPλ₯Ό μ΄μš©ν•΄ μ½”λ“œ μ™ΈλΆ€μ—μ„œ νŠΈλžœμž­μ…˜μ˜ κΈ°λŠ₯을 λΆ€μ—¬ν•΄μ£Όκ³  속성을 μ§€μ •ν•  수 있게 ν•˜λŠ” 방법
ν”„λ‘œκ·Έλž¨μ— μ˜ν•œ νŠΈλžœμž­μ…˜ programmatic transaction
  • κ°œλ³„ 데이터 기술의 νŠΈλžœμž­μ…˜ APIλ₯Ό μ‚¬μš©ν•΄ 직접 μ½”λ“œ μ•ˆμ—μ„œ μ‚¬μš©ν•˜λŠ” 방법

▢️ μŠ€ν”„λ§μ€ 두 κ°€μ§€ 경우 λͺ¨λ‘λ₯Ό μ§€μ›ν•˜κ³  μžˆλ‹€



ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•œ νŠΈλžœμž­μ…˜ μ–΄λ…Έν…Œμ΄μ…˜
  • ν…ŒμŠ€νŠΈ 클래슀/λ©”μ†Œλ“œμ— @Transactional μ–΄λ…Έν…Œμ΄μ…˜μ„ λΆ€μ—¬ν•΄μ£Όλ©΄ 마치 타깃 ν΄λž˜μŠ€λ‚˜ μΈν„°νŽ˜μ΄μŠ€μ— 적용된 κ²ƒμ²˜λŸΌ ν…ŒμŠ€νŠΈ λ©”μ†Œλ“œμ— νŠΈλžœμž­μ…˜ 경계가 μžλ™μœΌλ‘œ μ„€μ •
  • ν…ŒμŠ€νŠΈμ— 적용된 @Transactional 은 ν…ŒμŠ€νŠΈκ°€ λλ‚˜λ©΄ μžλ™ λ‘€λ°±λœλ‹€
    • κ°•μ œ 둀백이 μ•„λ‹Œ λ©”μ†Œλ“œ ν…ŒμŠ€νŠΈ λ‚΄μš©μ΄ DB에 λ°˜μ˜ν•˜κ³  μ‹Άλ‹€λ©΄ @Rollback 이용
    • λ©”μ†Œλ“œ 레벨이 μ•„λ‹Œ 클래슀 λ ˆλ²¨μ—μ„œ λΆ€μ—¬ν•˜λŠ” λ‘€λ°± 속성 지정은 @TransactionConfiguration
⚠️ **GitHub.com Fallback** ⚠️