[Spring] DI

Updated:

Categories:

Tags: ,

πŸ“Œ 개인적인 κ³΅κ°„μœΌλ‘œ 곡뢀λ₯Ό κΈ°λ‘ν•˜κ³  λ³΅μŠ΅ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•˜λŠ” λΈ”λ‘œκ·Έμž…λ‹ˆλ‹€.
μ •ν™•ν•˜μ§€ μ•Šμ€ 정보가 μžˆμ„ 수 μžˆμœΌλ‹ˆ μ°Έκ³ λ°”λžλ‹ˆλ‹€ :😸
[ν‹€λ¦° λ‚΄μš©μ€ λŒ“κΈ€λ‘œ λ‚¨κ²¨μ£Όμ‹œλ©΄ λ³΅λ°›μœΌμ‹€κ±°μ—μš”]

Spring Framework λͺ¨λ“ˆ ꡬ성 - μ•„ν‚€ν…μ²˜

  • 청사진
  • 기쑴에 ν‹€λ§Œ μžˆμ—ˆλ‹€λ©΄ μ–΄λ–€ μ»¨μ…‰μœΌλ‘œ μ„œλΉ„μŠ€λ₯Ό κ°–κ³  μžˆλŠ”μ§€ μœ μΆ”κ°€λŠ₯ν•œ 것.

μ‹œμŠ€ν…œ μ•„ν‚€ν…μ²˜

  • 인프라 μ•„ν‚€ν…μ²˜λΌκ³ λ„ 함
  • ν•˜λ“œμ›¨μ–΄μ™€ μ†Œν”„νŠΈμ›¨μ–΄λ₯Ό λͺ¨λ‘ ν¬ν•¨ν•˜λŠ” μ–΄λ–€ μ‹œμŠ€ν…œμ˜ 전체적인 ꡬ성을 큰 그림으둜 ν‘œν˜„ν•œ 것
  • μ»¨μ…‰λ§Œ λ³Ό 수 μžˆλ„λ‘ κ°„λ‹¨ν•˜κ²Œ 무엇을 λͺ©μ μœΌλ‘œ 인프라λ₯Ό κ΅¬μΆ•ν–ˆλŠ”μ§€ 보고 μ•Œ 수 μžˆλŠ” 것

예제

  1. μ±„νŒ…μ„œλ²„λ₯Ό κ΅¬μΆ•ν•˜κΈ° μœ„ν•œ 전톡적인 μ‹œμŠ€ν…œ μ•„ν‚€ν…μ²˜

    - 문제점

    • ν™•μž₯이 λΆˆκ°€λŠ₯
    • μ‚¬μš©μžκ°€ λ§Žμ•„μ§„λ‹€λ©΄ μœ„ 같은 μ•„ν‚€ν…μ²˜μ—λŠ” λ¬Έμ œκ°€ λ°œμƒ
  2. κ°œμ„ ν•œ μ•„ν‚€ν…μ²˜

    - μ•„ν‚€ν…μ²˜ μ‚¬μš©μžμ˜ μš”μ²­μ„ λΆ„μ‚°μ‹œμΌœ μ£ΌλŠ” λ‘œλ“œ λ°ΈλŸ°μ„œ μ˜μ—­μ„ λ‘μ–΄μ„œ μ›Ήμ†ŒμΌ“ μ„œλ²„λ₯Ό μ•ˆμ •μ μœΌλ‘œ 운영 - λ‘œλ“œλ°ΈλŸ°μ„œκ°€ λ‘œλ“œκ°€ λœλ˜λŠ” 곳에 λ³΄λ‚΄μ€Œ. - μ—¬λŸ¬ λŒ€μ˜ μ›Ήμ†ŒμΌ“ μ„œλ²„λ‘œ ν™•μž₯이 κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ— μ‚¬μš©μžμ˜ μš”μ²­μ΄ λŠ˜μ–΄λ‚˜λ”λΌλ„ μ„œλ²„μ˜ λΆ€ν•˜λ₯Ό 쀄일 수 있으며, νŠΉμ • μ„œλ²„μ— μž₯μ• κ°€ λ°œμƒν•˜λ”λΌλ„ 전체 μ‹œμŠ€ν…œμ΄ μ£½λŠ” 경우λ₯Ό λ°©μ§€κ°€λŠ₯

    • 1번 μ„œλ²„κ°€ λΆ€ν•˜κ°€ κ±Έλ €μ„œ 죽어도 λ‹€λ₯Έλ° 보내면 됨 - λ©”μ‹œμ§€ 브둜컀 μ˜μ—­μ„ λ‘μ–΄μ„œ μ›Ήμ†ŒμΌ“ μ„œλ²„κ°€ 닀쀑 μ„œλ²„λ‘œ ꡬ성이 λ˜μ–΄ μžˆλ”λΌλ„ νŠΉμ • μ‚¬μš©μžλ“€ 간에 λ©”μ‹œμ§€λ₯Ό 주고받을 수 μžˆλŠ” 곡유 채널을 μ‚¬μš©ν•˜λŠ” 것이 κ°€λŠ₯해짐.
    • λ©”μ„Έμ§€λΈŒλ‘œμ»€ - 상황을 κ³΅μœ ν•  수 있게 μ‹€μ‹œκ°„ μ†Œν†΅μ΄ κ°€λŠ₯ν•˜κ²Œ ν•΄μ€Œ.
  3. 전솑속도 ν–₯상을 μœ„ν•΄ κ°œμ„ λœ μ•„ν‚€ν…μ²˜

    • mongoDB -> 비관계성 DB
    • μ‚¬μš©μžμ˜ μš”μ²­κ³Ό μ„œλ²„μ˜ 응닡이 μ΄λ£¨μ–΄μ§€λŠ” 전체 μ˜μ—­μ— κ±Έμ³μ„œ Blocking λ˜λŠ” μš”μ†Œκ°€ 없도둝 λ¦¬μ•‘ν‹°λΈŒ μ‹œμŠ€ν…œμ„ κ΅¬μ„±ν•˜μ—¬ ν΄λΌμ΄μ–ΈνŠΈμ˜ μš”μ²­μ„ 보닀 λΉ λ₯΄κ²Œ μ²˜λ¦¬κ°€λŠ₯
    • μ›Ήμ†ŒμΌ“μ΄ ν•˜λ‚˜μ˜ Connectionκ³Ό μ—°κ²°λ˜λŠ” 것에 λ°˜ν•΄ RSocket은 ν•˜λ‚˜μ˜ Connection λ‚΄μ—μ„œ 닀쀑 μš”μ²­ μ²˜λ¦¬κ°€ κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ— λŒ€λŸ‰μ˜ μš”μ²­μ„ μ•ˆμ •μ μœΌλ‘œ μ²˜λ¦¬κ°€



μ†Œν”„νŠΈμ›¨μ–΄ μ•„ν‚€ν…μ²˜

λŒ€ν‘œ 사둀 : Java ν”Œλž«νΌ μ•„ν‚€ν…μ²˜

​

  1. μ• ν”Œλ¦¬μΌ€μ΄μ…˜
    1. μ†Œν”„νŠΈμ›¨μ–΄ μ’…λ₯˜μ˜ ν•˜λ‚˜λ‘œμ¨ μ’κ²ŒλŠ” λ°μŠ€ν¬ν†±μ΄λ‚˜ μŠ€λ§ˆνŠΈν°μ—μ„œ μ‚¬μš©ν•˜λŠ” μ‘μš© ν”„λ‘œκ·Έλž¨μ„ 말함
    2. λ„“κ²ŒλŠ” ν΄λΌμ΄μ–ΈνŠΈμ˜ μš”μ²­μ„ μ²˜λ¦¬ν•˜λŠ” μ„œλ²„ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ 의미
  2. μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μœ„ν•œ μ•„ν‚€ν…μ²˜ β‡’ 이것을 λͺ…ν™•ν•˜κ²Œ 잘 μ§€ν‚€κ³  μžˆλŠ” 것이 MVC

    μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ³„μΈ΅ν˜•μœΌλ‘œ ν‘œν˜„ν•œ μ•„ν‚€ν…μ²˜ - κ³„μΈ΅ν˜• μ•„ν‚€ν…μ²˜(N-ν‹°μ–΄)

  • API 계측(API Layer)은 ν΄λΌμ΄μ–ΈνŠΈμ˜ μš”μ²­μ„ λ°›μ•„λ“€μ΄λŠ” 계측
    • 일반적으둜 ν‘œν˜„ 계측(Presentation Layer)이라고도 뢈리고
    • REST APIλ₯Ό μ œκ³΅ν•˜λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 경우 API 계측이라고 ν‘œν˜„
  • μ„œλΉ„μŠ€κ³„μΈ΅(Service Layer) = λΉ„μ¦ˆλ‹ˆμŠ€ 계측은 API κ³„μΈ΅μ—μ„œ 전달받은 μš”μ²­μ„ 업무 λ„λ©”μΈμ˜ μš”κ΅¬ 사항에 맞게 λΉ„μ¦ˆλ‹ˆμŠ€μ μœΌλ‘œ μ²˜λ¦¬ν•˜λŠ” 계측이닀.
  • 데이터 μ•‘μ„ΈμŠ€ 계측(Data Access Layer)은 λΉ„μ¦ˆλ‹ˆμŠ€ κ³„μΈ΅μ—μ„œ 처리된 데이터λ₯Ό λ°μ΄ν„°λ² μ΄μŠ€ λ“±μ˜ 데이터 μ €μž₯μ†Œμ— μ €μž₯ν•˜κΈ° μœ„ν•œ 계측
  • μœ„ 계측을 μ•„λž˜μ²˜λŸΌ κ΅¬ν˜„ κ°€λŠ₯.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
      @Controller, Rest
        
      Class User Controller{
        
      }
        
      @SERVICE
        
      Class UserService{
        
      }
        
      @Repository
        
      Class UserRepository{
      }
    
    • MVCλ₯Ό λΉΌκ³  κ°œλ°œν•˜λŠ” κ²½μš°λŠ” μ—†μŒ. (μ›Ήν”ŒλŸ­μŠ€(=비동기 Framework)μ‚¬μš©ν•  λ•Œ λΉΌκ³ ) μ•žμœΌλ‘œ 이런 ꡬ쑰λ₯Ό μ² μ €ν•˜κ²Œ 따라야 함.
    • controller만 κ΅¬ν˜„ν•˜λ©΄ client와 데이터 주고받을 수 있음. = 정상적 app은 μ•„λ‹˜



μ•„ν‚€ν…μ²˜λ‘œ λ³΄λŠ” Spring Framework λͺ¨λ“ˆ(Module) ꡬ성

  • Spring Framework의 λͺ¨λ“ˆ μ•„ν‚€ν…μ²˜λ₯Ό 톡해 Spring이 μ–΄λ–€ κΈ°λŠ₯듀을 μ§€μ›ν•˜λŠ”μ§€ μ•Œ 수 있음

​

λͺ¨λ“ˆ(Module)μ΄λž€? Javaμ—μ„œλŠ” 일반적으둜, μ§€μ›λ˜λŠ” μ—¬λŸ¬ κ°€μ§€ κΈ°λŠ₯듀을 λͺ©μ μ— 맞게 κ·Έλ£Ήν™”ν•˜μ—¬ λ¬Άμ–΄ 놓은 것

μ΄λŸ¬ν•œ λͺ¨λ“ˆλ“€μ€ Java의 νŒ¨ν‚€μ§€ λ‹¨μœ„λ‘œ λ¬Άμ—¬ 있으며, 이 νŒ¨ν‚€μ§€ μ•ˆμ—λŠ” κ΄€λ ¨ κΈ°λŠ₯을 μ œκ³΅ν•˜κΈ° μœ„ν•œ ν΄λž˜μŠ€λ“€μ΄ ν¬ν•¨λ˜μ–΄ 있음.

일반적으둜 λͺ¨λ“ˆμ€ μž¬μ‚¬μš© κ°€λŠ₯ν•˜λ„λ‘ 라이브러리 ν˜•νƒœλ‘œ μ œκ³΅λ˜λŠ” κ²½μš°κ°€ 많음.



DI

DI(Dependency Injection) -μ½”λ“œλ‘œ μ΄ν•΄ν•˜κΈ°

DI 방법 -3κ°€μ§€

  1. μƒμ„±μž
    1. μƒμ„±μžλ₯Ό 톡해 객체의 참쑰값이 μ£Όμž… - κ³΅μ‹λ¬Έμ„œμ—μ„œ ꢌμž₯ν•˜λŠ” 방법

    Dependency Injection :: Spring Framework

  2. Setter λ©”μ„œλ“œλ₯Ό ν†΅ν•œ μ£Όμž…
  3. ν•„λ“œμ— 직접 μ£Όμž… - κ³΅μ‹λ¬Έμ„œμ—μ„œλ„ 사라짐

예제

  1. kiosk 클래슀

    1
    2
    3
    4
    5
    6
    7
    
     public class KioskApplication implements CommandLineRunner {    
         private Kiosk kiosk;
     		@Autowired
         public KioskApplication(Kiosk kiosk) {
             this.kiosk = kiosk;
         }
     }
    
  2. kioskApplication 클래슀

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
     public class Kiosk {
         private MenuItem[] menuItemArray;
         private Printer printer;
         private DiscountPolicy discountPolicy;
        
         @Autowired
         public Kiosk(MenuItem[] menuItemArray, Printer printer, DiscountPolicy discountPolicy) {
             this.menuItemArray = menuItemArray;
             this.printer = printer;
             this.discountPolicy = discountPolicy;
         }
    
  3. 1번과 2번의 곡톡점
    1. μ™ΈλΆ€λ‘œλΆ€ν„° νŠΉμ •ν•œ 객체λ₯Ό μ£Όμž… λ°›μ•„ this ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ λ‚΄λΆ€ν•„λ“œμ— ν• λ‹Ήν•˜μ—¬ 값을 μ‚¬μš©
    2. λͺ¨λ‘ μƒμ„±μžλ₯Ό 톡해 객체λ₯Ό μ£Όμž…λ°›μŒ(DI)
      • KioskApplication : kiosk에 의쑴
      • kiosk : MenuItem, Printer, discountPolicy에 의쑴
  4. μ ‘κ·Όμ œμ–΄μž private
    1. μΊ‘μŠν™” β†’ λ‚΄λΆ€μ—μ„œ μ‚¬μš©λ˜λŠ” 데이터듀이 개발자의 μ‹€μˆ˜ λ˜λŠ” μ–΄λ–€ 원인을 톡해 μž„μ˜λ‘œ λ³€κ²½λ˜μ§€ μ•Šλ„λ‘ λ³΄ν˜Έν•˜κ³  μ™ΈλΆ€λ‘œμ˜ λ…ΈμΆœμ„ λ°©μ§€ν•˜κΈ° μœ„ν•œ 것
  5. private final

    1. final
      • 레퍼런슀 νƒ€μž…μΌ λ•Œ μ£Όμ†Œ κ°’ λ³€κ²½ λΆˆκ°€λŠ₯해짐 β‡’ 값을 더이상 λͺ»λ°”κΏˆ, μš”μ†Œμ—λŠ” μ ‘κ·Ό 및 λ³€κ²½ κ°€λŠ₯

      • μƒμ„±μž μ£Όμ„μ²˜λ¦¬ ν–ˆμ„ λ•Œ λΉ¨κ°„ 쀄 λœ¨λŠ” 이유 = μ΄ˆκΈ°ν™”κ°€ λ˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έ β‡’ 무쑰건 μ΄ˆκΈ°ν™”κ°€ λ˜μ–΄μ•Ό 함.
      • final 이 λΆ™κ³  μƒμ„±μžλ₯Ό λ§Œλ“€λ©΄ NPAλ₯Ό λ°©μ§€ν•  수 있음
      • μ΄ˆκΈ°ν™”λ₯Ό 톡해 Null 값이 λ“€μ–΄μ˜¬ 일이 μ•ˆ μƒκΈ°κ²Œ ν•˜κΈ° μœ„ν•΄ β‡’ NPAλ₯Ό ν”Όν•˜κΈ° μœ„ν•œ κ°€μž₯ 기본적인 νŒ¨ν„΄
  6. AppConfig 클래슀 β‡’ DIλ₯Ό 톡해 λ³€κ²½κ³Ό ν™•μž₯에 μœ μ—°ν•œ μ½”λ“œλ₯Ό 섀계

    1
    2
    3
    4
    5
    
     @Bean
     public DiscountPolicy discountPolicy() {
         return new FixedAmountDiscountPolicy(100); 
         // 할인 κΈˆμ•‘μ„ μ—¬κΈ°μ„œ μ„€μ •
     }
    
    • DiscountPolicy 클래슀의 μƒμ„±μžλŠ” 객체가 μ΅œμ΄ˆμ— 생성될 λ•Œ, 각각 μ •λ₯  할인(FixedRateDiscountPolicy)κ³Ό μ •μ•‘ 할인(FixedAmountDiscountPolicy)이 적용될 수 μžˆλ„λ‘ 객체듀 κ°„ 의쑴 관계λ₯Ό κ΅¬μ„±ν•˜λŠ” 역할을 μˆ˜ν–‰
    • 할인 정책을 λ³€κ²½ν•˜κ³  싢을 λ•Œ returnκ°’μ˜ 객체만 λ³€κ²½ν•΄μ£Όλ©΄ 됨.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      
        @Configuration
        public class AppConfig {
            @Bean
            public DiscountPolicy discountPolicy() {
                return new **FixedRateDiscountPolicy(20);**
            }
              
            --- μƒλž΅ ---
        }
      
  7. @bean, @configuration
    1. @Bean 은 μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ—μ„œ 관리할 λΉˆμ„ μ •μ˜
    2. @Configuration객체가 Bean μ •μ˜μ˜ μ†ŒμŠ€μž„μ„ λ‚˜νƒ€λ‚΄λŠ” 클래슀 μˆ˜μ€€ 주석, μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆκ°€ 관리할 λΉˆμ„ μ •μ˜ν•˜λŠ” ν΄λž˜μŠ€μž„μ„ λͺ…μ‹œν•˜λŠ” 데 μ‚¬μš©λ¨
    3. λ§Œμ•½ discountPolicyκ°€ 2κ°œκ°€ μžˆλŠ”λ°

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      
       @Bean
       public DiscountPolicy discountPolicy(){
       	return new FixedAmountDiscountPolicy(100); 
       			//1. ν• μΈκΈˆμ•‘μ„ μ—¬κΈ°μ„œ μ„€μ •
       }
       @Bean
       public DiscountPolicy discountPolicy2(){
       	return new FixedRateDiscountPolicy(0.2);
       	// 2. 할인λ₯ μ„ μ—¬κΈ°μ„œ μ„€μ •
       }
      

      μ•„λž˜ ν‚€μ˜€μŠ€ν¬λ₯Ό μ‹€ν–‰ν•˜κ²Œ 되면 λ‘˜ 쀑에 μ–΄λ–€ 할인 정책이 λ°˜ν™˜λ κΉŒ?

      ​

      • 1번 ν• μΈκΈˆμ•‘μ„ μ„€μ •ν•œ FixedAmountDiscountPolicyκ°€ λ°˜ν™˜λ¨
      • μ΄μœ λŠ” @bean은 μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— 넣을 λ•Œ λ°˜ν™˜ν•˜λŠ” 객체의 λ©”μ„œλ“œ μ΄λ¦„μœΌλ‘œ λ“€μ–΄κ°€κ²Œ 되고 ν˜ΈμΆœν•  경우 객체의 이름 λ¨Όμ € 확인 ν›„ λ³€μˆ˜λͺ… 확인 β‡’ λ˜‘κ°™μ€ 이름을 κ°€μ§„ ν• μΈκΈˆμ•‘μœΌλ‘œ μ„€μ •ν•΄μ€€ λ©”μ„œλ“œκ°€ 반영됨.




μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ™€ 빈

빈; μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆκ°€ κ΄€λ¦¬ν•˜λŠ” μžλ°” 객체λ₯Ό μŠ€ν”„λ§ 빈(Bean), μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” 메타 정보λ₯Ό 기반으둜 μŠ€ν”„λ§ 빈 생성 함.

μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ˜ 생성

ApplicationContext μΈν„°νŽ˜μ΄μŠ€λ₯Ό 일반적으둜 μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλΌ 함.

  1. BeanFactory
    1. μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ˜ μ΅œμƒμœ„ μΈν„°νŽ˜μ΄μŠ€λ‘œ μŠ€ν”„λ§ λΉˆμ„ κ΄€λ¦¬ν•˜κ³  μ‘°νšŒν•˜λŠ” 역할을 λ‹΄λ‹Ή - getBean() λ©”μ„œλ“œ 제곡 주체

      ✨✨✨✨✨✨✨✨✨✨✨✨✨✨

  2. ApplicationContext μΈν„°νŽ˜μ΄μŠ€

    • ApplicationContextλŠ” BeanFactory둜 λΆ€ν„° ν™•μž₯된 μΈν„°νŽ˜μ΄μŠ€ 뿐만 μ•„λ‹ˆλΌ EnvironmentCapable, MessageSource, ApplicationEventPublisher, ResourcePatternResolver λ“± λ‹€μ–‘ν•œ κΈ°λŠ₯의 μΈν„°νŽ˜μ΄μŠ€λ“€μ„ 상속 λ°›μ•„ μ‚¬μš© (μΈν„°νŽ˜μ΄μŠ€λŠ” 닀쀑 상속이 κ°€λŠ₯, μ•ž λ’€ μ „λΆ€λ‹€ μΈν„°νŽ˜μ΄μŠ€ μž„μ„ μ•Œ 수 있음)
    • μ΄λŸ¬ν•œ μΈν„°νŽ˜μ΄μŠ€λ“€μ€ ν™˜κ²½ λ³€μˆ˜ μ„€μ •, λ©”μ‹œμ§€ κ΅­μ œν™” κΈ°λŠ₯, 이벀트 λ°œμƒ, λ¦¬μ†ŒμŠ€ 쑰회 λ“± λ‹€μ–‘ν•œ κΈ°λŠ₯듀을 지원
    • 즉, ApplicationContextλŠ” λΉˆμ„ κ΄€λ¦¬ν•˜κ³  μ‘°νšŒν•˜λŠ” κΈ°λŠ₯ 뿐 μ•„λ‹ˆλΌ μ›Ή μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ κ°œλ°œν•˜λŠ” 데 ν•„μš”ν•œ λ‹€μ–‘ν•œ λΆ€κ°€ κΈ°λŠ₯듀을 ν•¨κ»˜ 제곡

    μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” μš°λ¦¬κ°€ ν–ˆλ˜ κ²ƒμ²˜λŸΌ μ• λ„ˆν…Œμ΄μ…˜ 기반 μžλ°” μ„€μ • ν΄λž˜μŠ€λ‘œλ„ λ§Œλ“€ 수 μžˆμ§€λ§Œ, XML(Extensible Markup Language)λ₯Ό 기반으둜 μƒμ„±ν•˜λŠ” 것도 κ°€λŠ₯ XML은 데이터λ₯Ό μ •μ˜ν•˜λŠ” κ·œμΉ™μ„ μ œκ³΅ν•˜λŠ” λ§ˆν¬μ—… μ–Έμ–΄λ‘œμ„œ, 컴퓨터 μ‹œμŠ€ν…œ κ°„μ˜ 곡유 κ°€λŠ₯ν•œ λ°©μ‹μœΌλ‘œ 데이터λ₯Ό μ •μ˜ν•˜κ³  μ €μž₯ν•  수 있음

  3. AnnotationConfigApplicationContext
    • κ·Έ κ΅¬ν˜„ 객체이며 λ§€κ°œλ³€μˆ˜λ‘œ ꡬ성 정보(AppConfig.class)λ₯Ό λ„˜κ²¨μ£Όκ³  있음.



μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ™€ 빈

  1. μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” μ΄λ ‡κ²Œ λ„˜κ²¨λ°›μ€ ꡬ성 정보λ₯Ό κ°€μ§€κ³  λ©”μ„œλ“œλ“€μ„ ν˜ΈμΆœν•˜μ—¬ λΉˆμ„ μƒμ„±ν•˜κ³ , λΉˆλ“€ κ°„μ˜ 의쑴 관계λ₯Ό μ„€μ •
  2. λΉˆμ„ μƒμ„±ν•˜λŠ” κ³Όμ •μ—μ„œ, μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” ν˜ΈμΆœλ˜λŠ” λ©”μ„œλ“œμ˜ 이름을 κΈ°μ€€μœΌλ‘œ 빈의 이름을 등둝
    • 예λ₯Όλ“€μ–΄ discountPolicy() λ©”μ„œλ“œμ˜ 호좜결과둜
    • λ°˜ν™˜λœ new FixedAmountDiscountPolicy(100) 객체 λΉˆμ€
    • discountPolicy λΌλŠ” μ΄λ¦„μœΌλ‘œ μŠ€ν”„λ§μ»¨ν…Œμ΄λ„ˆμ— μ €μž₯됨.

      1
      2
      3
      4
      5
      6
      7
      
        @Configuration
        public class AppConfig {
              
            @Bean
            public DiscountPolicy discountPolicy() {
                return new FixedAmountDiscountPolicy(100); // 할인 κΈˆμ•‘μ„ μ—¬κΈ°μ„œ μ„€μ •
            }
      
  3. 빈 이름 μ„€μ •κ³Ό 쑰회
    1. μ„€μ • : @Bean(name=”~”)

      1
      2
      3
      4
      5
      6
      7
      8
      
       @Configuration
       public class AppConfig {
              
           @Bean(name="discountPolicy2")
           public DiscountPolicy discountPolicy() {
               return new FixedAmountDiscountPolicy(100); // 할인 κΈˆμ•‘μ„ μ—¬κΈ°μ„œ μ„€μ •
           }
              
      
      • λ§Œμ•½ μœ„μ™€ 같은 λ°©μ‹μœΌλ‘œ 빈의 이름을 등둝해 쀄 μ‹œ, 같은 μ΄λ¦„μ˜ 빈이 λ“±λ‘λ˜λŠ” 경우 μ—λŸ¬μ˜ 원인이 λ˜λ―€λ‘œ, 항상 λ‹€λ₯Έ μ΄λ¦„μ˜ λΉˆμ„ μƒμ„±ν•˜λ„λ‘ 주의
    2. 쑰회

      • λΉˆμ€ 클래슀의 등둝 정보, getter/setter λ©”μ„œλ“œλ₯Ό ν¬ν•¨ν•˜λ©°, μ•žμ„œ λ³Έ κ²ƒμ²˜λŸΌ ꡬ성 정보(μ„€μ • 메타 정보)λ₯Ό 톡해 생성

      • μš°λ¦¬κ°€ λ„˜κΈ΄ ꡬ성 정보λ₯Ό ν† λŒ€λ‘œ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆκ°€ λΉˆμ„ μƒμ„±ν•˜κ³  의쑴 관계λ₯Ό μ—°κ²°ν•΄ μ£Όλ©΄ 이제 μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ˜ 관리 ν•˜μ— μžˆλŠ” 객체 λΉˆλ“€μ„ μ•„λž˜μ™€ 같이 getBean() λ©”μ„œλ“œλ‘œ μ‘°νšŒκ°€λŠ₯
      • getBean(빈 이름, νƒ€μž…) λ˜λŠ” getBean(νƒ€μž…)

        1
        2
        3
        4
        5
        6
        
          DiscountPolicy discountPolicy 
          	= applicationContext.getBean("discountPolicy", DiscountPolicy.class);
                    	
          	λ˜λŠ” 
                    	
          	= applicationContext.getBean(DiscountPolicy.class);
        
        1. getBean(νƒ€μž…)으둜 bean μ‘°νšŒμ‹œ 같은 νƒ€μž…μ˜ 객체가 두 개 이상 μžˆλŠ” 경우 였λ₯˜ λ°œμƒ
  4. Main μ‹€ν–‰ 클래슀
    1. λͺ¨λ“  빈 쑰회

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
       public class Main {
           public static void main(String[] args) {
              
       			// (2) λͺ¨λ“  빈 쑰회
       	    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfigurer.class);
              
       			String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
              
       				for (String beanDefinitionName : beanDefinitionNames) {
                   Object bean = applicationContext.getBean(beanDefinitionName);
                   System.out.println("beanName=" + beanDefinitionName + " object=" + bean);
               }
       }
              
      
      • getBeanDefinitionNames() λ©”μ„œλ“œ μ‚¬μš©μ‹œ μŠ€ν”„λ§μ»¨ν…Œμ΄λ„ˆκ°€ κ΄€λ¦¬ν•˜λŠ” λͺ¨λ“  빈 쑰회 κ°€λŠ₯
    2. 빈 메타 정보 쑰회

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
       public class Main {
           public static void main(String[] args) {
              
       			// (2) 빈 메타정보 쑰회
       			AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfigurer.class);
              
       			String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
              
               for (String beanDefinitionName : beanDefinitionNames) {
                   BeanDefinition beanDefinition = applicationContext.getBeanFactory().getBeanDefinition(beanDefinitionName);
                   System.out.println("Bean name: " + beanDefinitionName + ", Scope: " + beanDefinition.getScope());
               }
       }
              
      


ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€ μž‘μ„± 기초

  1. λ‹¨μœ„ν…ŒμŠ€νŠΈ
    1. μž‘μ€ λ‹¨μœ„μ˜ μ–΄λ–€ νŠΉμ •ν•œ κΈ°λŠ₯을 ν…ŒμŠ€νŠΈν•˜κ³ , κ²€μ¦ν•˜κΈ° μœ„ν•œ 도ꡬλ₯Ό 의미
    2. = ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€(Test Case)λ₯Ό μž‘μ„±ν•œλ‹€κ³ λ„ ν‘œν˜„
    3. μž…λ ₯ 데이터, μ‹€ν–‰ 쑰건, 그리고 κΈ°λŒ€ 결과에 λŒ€ν•œ 값이 포함
    4. μŠ€ν”„λ§μ—μ„œ JUnitμ΄λΌλŠ” μ˜€ν”ˆ μ†ŒμŠ€ ν…ŒμŠ€νŠΈ ν”„λ ˆμž„μ›Œν¬λ₯Ό 제곡
      1. 각각의 λ‹¨μœ„ ν…ŒμŠ€νŠΈλŠ” λ©”μ„œλ“œ λ‹¨μœ„λ‘œ μž‘μ„±
  2. JUnit
    1. test 디렉토리 μ•ˆμ—μ„œ μž‘μ„±λ˜λŠ” 것을 원칙
    2. ν…ŒμŠ€νŠΈ ν΄λž˜μŠ€λŠ” κ΄€λ‘€μ μœΌλ‘œ ν…ŒμŠ€νŠΈμ˜ λŒ€μƒμ΄ λ˜λŠ” 클래슀의 이름에 Testλ₯Ό λΆ™μ—¬ 클래슀λ₯Ό 생성
    3. 기본ꡬ쑰- 각 κ²€μ¦ν•˜κ³ μž ν•˜λŠ” κΈ°λŠ₯ λ‹¨μœ„μ— 따라 λ©”μ„œλ“œλ‘œ μž‘μ„±

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      
       import org.junit.jupiter.api.Test;
              
       public class JunitDefaultStructure {
              
           @Test
           public void test1() {
            // ν…ŒμŠ€νŠΈν•˜κ³ μž ν•˜λŠ” λŒ€μƒμ— λŒ€ν•œ ν…ŒμŠ€νŠΈ 둜직 μž‘μ„±
           }
              
           @Test
           public void test2() {
            // ν…ŒμŠ€νŠΈν•˜κ³ μž ν•˜λŠ” λŒ€μƒμ— λŒ€ν•œ ν…ŒμŠ€νŠΈ 둜직 μž‘μ„±
           }
              
           @Test
           public void test3() {
            // ν…ŒμŠ€νŠΈν•˜κ³ μž ν•˜λŠ” λŒ€μƒμ— λŒ€ν•œ ν…ŒμŠ€νŠΈ 둜직 μž‘μ„±
           }
       }
              
      




ν…ŒμŠ€νŠΈ 둜직 μž‘μ„±

  1. 예제 -MainTest 클래슀 - 빈 쑰회 λ‹¨μœ„ ν…ŒμŠ€νŠΈ μž‘μ„±

    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
    
     package com.springboot.v2;
        
     import com.springboot.v2.discount.DiscountPolicy;
     import org.assertj.core.api.Assertions;
     import org.junit.jupiter.api.Test;
     import org.springframework.context.annotation.AnnotationConfigApplicationContext;
        
     import static org.junit.jupiter.api.Assertions.*;
        
     class KioskApplicationTest {
         // μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆ 생성
         AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        
         // 빈 쑰회 ν…ŒμŠ€νŠΈμΌ€μ΄μŠ€
         @Test
         void findBean() {
        
             // (1) given => μ΄ˆκΈ°ν™” λ˜λŠ” ν…ŒμŠ€νŠΈμ— ν•„μš”ν•œ μž…λ ₯ 데이터
             AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        
             // (2) when => ν…ŒμŠ€νŠΈ ν•  λ™μž‘
             DiscountPolicy discountPolicy = applicationContext.getBean("discountPolicy", DiscountPolicy.class);
        
             // (3) then => 검증
             Assertions.assertThat(discountPolicy).isInstanceOf(DiscountPolicy.class);
         }
     }
    
  2. ν…ŒμŠ€νŠΈ μ‹€ν–‰

  3. 좜λ ₯

  4. λΉ„μ¦ˆλ‹ˆμŠ€ 둜직

    1. given - when - then 은 BDD(Behavior Driven Development)라고 λΆ€λ₯΄λŠ” ν…ŒμŠ€νŠΈ λ°©μ‹μ—μ„œ μ‚¬μš©λ˜λŠ” 방법

    (1) given: μž…λ ₯ 데이터

    • ν…ŒμŠ€νŠΈμ— ν•„μš”ν•œ μ΄ˆκΈ°ν™” κ°’ λ˜λŠ” μž…λ ₯ 데이터λ₯Ό 의미
    • μœ„μ˜ 예제의 경우, 빈 쑰회 ν…ŒμŠ€νŠΈμ— ν•„μš”ν•œ μ΄ˆκΈ°ν™” μ„ΈνŒ…μ€ AppConfigurer 클래슀λ₯Ό ꡬ성 μ •λ³΄λ‘œ ν•˜λŠ” μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλ₯Ό μƒμ„±ν•˜λŠ” 것

    (2) when: μ‹€ν–‰ λ™μž‘

    • ν…ŒμŠ€νŠΈν•  μ‹€ν–‰ λ™μž‘μ„ μ§€μ •.
    • 빈 쑰회 ν…ŒμŠ€νŠΈμ—μ„œ μ‹€ν–‰ν•  λ™μž‘μ€ getBean() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ λΉˆμ„ λΆˆλŸ¬μ˜€λŠ” 것

    (3) then: κ²°κ³Ό 검증

    • ν…ŒμŠ€νŠΈμ˜ κ²°κ³Όλ₯Ό μ΅œμ’…μ μœΌλ‘œ κ²€μ¦ν•˜λŠ” 단계
    • 일반적으둜 ν…ŒμŠ€νŠΈ κ²°κ³Ό μ˜ˆμƒλ˜λŠ” κΈ°λŒ€κ°’(expected)κ³Ό μ‹€μ œ μ‹€ν–‰ 결과의 값을 λΉ„κ΅ν•˜μ—¬ ν…ŒμŠ€νŠΈλ₯Ό 검증
    • 주둜 JUnit λ˜λŠ” AssertJ λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ μ œκ³΅ν•˜λŠ” Assertions 클래슀의 κΈ°λŠ₯듀을 ν•„μš”μ— 따라 μ‚¬μš©ν•˜μ—¬ 검증을 진행함
    • μœ„μ˜ μ½”λ“œλŠ” AssertJ 라이브러리의 Assertions 클래슀의 λ©”μ„œλ“œμΈ assertThat()을 μ‚¬μš©ν•œ 검증 방법
    • AssertJλŠ” λ©”μ„œλ“œ 체이닝(method chaining)을 μ§€μ›ν•˜κΈ° λ•Œλ¬Έμ— 슀트림과 μœ μ‚¬ν•˜κ²Œ μ—¬λŸ¬ λ©”μ„œλ“œλ“€μ„ μ—°μ†ν•˜μ—¬ ν˜ΈμΆœν•˜μ—¬ κ°„νŽΈν•˜κ²Œ μ‚¬μš©μ΄ κ°€λŠ₯
    • AssertJμ—μ„œ λͺ¨λ“  ν…ŒμŠ€νŠΈμ½”λ“œλŠ” assertThat()을 μ‚¬μš©ν•˜κ³ , ν…ŒμŠ€νŠΈλ₯Ό μ‹€ν–‰ν•  λŒ€μƒμ„ νŒŒλΌλ―Έν„°λ‘œ μ „λ‹¬ν•˜μ—¬ 호좜, 호좜의 결과둜 ObjectAssert νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€λ₯Ό λ°˜ν™˜ν•˜λŠ”λ°, 이λ₯Ό μ‚¬μš©ν•˜μ—¬ isInstanceOf() , isSameAs() , isNotNull() , isNotEmpty() λ“± λ‹€μ–‘ν•œ 검증을 νŽΈλ¦¬ν•˜κ²Œ μ‹€ν–‰κ°€λŠ₯.
    • μš°λ¦¬κ°€ μž‘μ„±ν•œ μ½”λ“œλ₯Ό 해석해 보면, λ¨Όμ € Assertions.assertThat() λ©”μ„œλ“œμ— ν…ŒμŠ€νŠΈλ₯Ό μ‹€ν–‰ν•  μ°Έμ‘°λ³€μˆ˜ discountPolicyλ₯Ό μ „λ‹¬μΈμžλ‘œ μ „λ‹¬ν•˜κ³ , λ©”μ„œλ“œ 체이닝을 μ‚¬μš©ν•˜μ—¬ isInstanceOf() λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜κ³  있음
    • isInstanceOf() λ©”μ„œλ“œλŠ” λŒ€μƒ 타이 μ£Όμ–΄μ§„ μœ ν˜•μ˜ μΈμŠ€ν„΄μŠ€μΈμ§€ 검증할 λ•Œμ— μ‚¬μš©, μžλ°”μ˜ instanceOf() λ©”μ„œλ“œμ™€ μœ μ‚¬ν•˜λ‹€κ³  ν•  수 μžˆμŠ΅λ‹ˆλ‹€.


μŠ€ν”„λ§μ»¨ν…Œμ΄λ„ˆ(=Singleton container)- μ΄ν•΄μ•ˆκ°

  1. μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” 싱글톀 μ»¨ν…Œμ΄λ„ˆ 역할을 μˆ˜ν–‰
  2. μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” 싱글톀 λ ˆμ§€μŠ€νŠΈλ¦¬ κΈ°λŠ₯을 κ°€μ§€κ³  μžˆλŠ” 싱글톀 μ»¨ν…Œμ΄λ„ˆμ΄κΈ° λ•Œλ¬Έμ— κ·Έ μ•ˆμ—μ„œ μƒμ„±λ˜κ³  κ΄€λ¦¬λ˜λŠ” 객체듀이 μ‹±κΈ€ν†€μœΌλ‘œ 관리됨
  3. μ‹±κΈ€ν†€μœΌλ‘œ 객체λ₯Ό 생성 및 κ΄€λ¦¬ν•˜λŠ” κΈ°λŠ₯을 싱글톀 λ ˆμ§€μŠ€νŠΈλ¦¬(Singleton Registry)

  4. μ‹±κΈ€ν†€νŒ¨ν„΄
    1. νŠΉμ • 클래슀의 μΈμŠ€ν„΄μŠ€κ°€ 단 ν•˜λ‚˜λ§Œ μƒμ„±λ˜λ„λ‘ 보μž₯ν•˜λŠ” λ””μžμΈ νŒ¨ν„΄
    2. 고객의 μš”μ²­λ§ˆλ‹€ new μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•˜μ—¬ 객체λ₯Ό μƒμ„±ν•˜λ©΄ 큰 λ©”λͺ¨λ¦¬ λ‚­λΉ„λ₯Ό 초래.
    3. 싱글톀 νŒ¨ν„΄μ„ κ΅¬ν˜„ν•˜μ—¬ μ΅œμ΄ˆμ— 단 ν•˜λ‚˜μ˜ 객체λ₯Ό μƒμ„±ν•˜κ³  μš”μ²­μ΄ μžˆμ„ λ•Œλ§ˆλ‹€ 같은 객체λ₯Ό κ³΅μœ ν•˜λŠ” λ°©λ²•μœΌλ‘œ λ©”λͺ¨λ¦¬ λ‚­λΉ„λ₯Ό μ΅œμ†Œν™” ν•˜λŠ” 것이 κ°€λŠ₯.
  5. 예제 : 싱글톀을 μ μš©ν•˜μ—¬ μž‘μ„±ν•œ ν…ŒμŠ€νŠΈ μ½”λ“œ

    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
    32
    
     import org.assertj.core.api.Assertions;
     import org.junit.jupiter.api.Test;
        
     public class SingletonTest {
        
         // 싱글톀 κ΅¬ν˜„ O
         @Test
         void runWithSingleton() {
        
             TestConfig2 testConfig2 = new TestConfig2();
        
     				// productRepository 객체 생성
             ProductRepository productRepository = testConfig2.productRepository();
             ProductRepository productRepository2 = testConfig2.productRepository();
        
             // μƒμ„±ν•œ 두 개의 객체가 같은 참쑰값을 κ°€μ§€κ³  μžˆλŠ”μ§€ 검증
             Assertions.assertThat(productRepository).isSameAs(productRepository2);
         }
        
         // ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•œ TestConfig2 클래슀
         static class TestConfig2 {
        
             private final ProductRepository productRepository = new ProductRepository();
        
             private TestConfig2(){}
        
             public ProductRepository productRepository() {
                 return productRepository;
             }
         }
     }
        
    

    문제점

    • 싱글톀 νŒ¨ν„΄μ„ μ‚¬μš©ν•˜λ©΄ 반볡적으둜 μ‚¬μš©λ˜λŠ” 객체λ₯Ό 맀번 μƒˆλ‘­κ²Œ μƒμ„±ν•˜μ§€ μ•Šκ³  ν•˜λ‚˜μ˜ 객체λ₯Ό κ³΅μœ ν•˜μ—¬ λ©”λͺ¨λ¦¬ λ‚­λΉ„λ₯Ό μ΅œμ†Œν™”
    • μ§€μ–‘ν•˜λŠ” 것이 μ’‹μŒ β‡’ 객체 κ°„ 높은 결합도가 μ•ΌκΈ°λ˜κΈ° λ•Œλ¬Έ
    • λ˜ν•œ private final μ‚¬μš©μœΌλ‘œ λ³€κ²½κ³Ό ν™•μž₯의 어렀움

빈 생λͺ…주기와 λ²”μœ„

μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” 크게 μ΄ˆκΈ°ν™”μ™€ μ’…λ£ŒλΌλŠ” 생λͺ… μ£ΌκΈ°(life-cycle)λ₯Ό 가짐

  1. 빈 객체 생λͺ… μ£ΌκΈ°

    (1) κ°€μž₯ λ¨Όμ € 빈 객체듀을 생성

    (2) 객체듀 κ°„ 의쑴 관계λ₯Ό μ„€μ •

    (3) 의쑴 관계 섀정이 μ™„λ£Œλ˜λ©΄ λ‚΄λΆ€μ μœΌλ‘œ μ§€μ •ν•œ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ—¬ 빈 객체의 μ΄ˆκΈ°ν™”λ₯Ό μ§„ν–‰

    (4) 빈 κ°μ²΄λ“€μ˜ μ‚¬μš©μ΄ 마무리되고 μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆκ°€ μ’…λ£Œλ˜λ©΄, μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” μ§€μ •ν•œ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ—¬ 빈 κ°μ²΄λ“€μ˜ μ†Œλ©Έμ„ 처리

  2. μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ™€ 빈 객체 생λͺ…μ£ΌκΈ° 이해 ν•„μš”μ„±
    1. ν•„μš”ν•œ κΈ°λŠ₯ κ΅¬ν˜„μ„ ν•˜κΈ° μœ„ν•¨

      Ex) λ°μ΄ν„°λ² μ΄μŠ€μ˜ 컀λ„₯μ…˜ ν’€, μ±„νŒ… ν΄λΌμ΄μ–ΈνŠΈμ˜ κΈ°λŠ₯ λ“±μ˜ κ΅¬ν˜„

      1. 컀λ„₯μ…˜ 풀을 μœ„ν•œ 빈 κ°μ²΄λŠ” λ°μ΄ν„°λ² μ΄μŠ€λ₯Ό μ—°κ²°ν•˜λ©°, μ±„νŒ… ν΄λΌμ΄μ–ΈνŠΈλŠ” μ„œλ²„μ™€μ˜ 연결을 μ§„ν–‰
      2. λ°˜λŒ€λ‘œ, μ»¨ν…Œμ΄λ„ˆκ°€ μ’…λ£Œλ˜μ–΄ 빈 객체가 μ†Œλ©Έλ˜λŠ” μ‹œμ μ—μ„œλŠ” λ°μ΄ν„°λ² μ΄μŠ€ λ˜λŠ” μ„œλ²„μ™€μ˜ 연결을 μ μ ˆν•˜κ²Œ λŠμ–΄λ‚Ό 수 μžˆμ–΄μ•Ό 함
  3. μŠ€ν”„λ§μ€ 의쑴 관계 섀정이 μ™„λ£Œλœ μ‹œμ κ³Ό μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ˜ μ’…λ£Œ μ§μ „μ˜ μ‹œμ μ— μ§€μ •λœ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ—¬ 개발자둜 각각의 μ‹œμ μ— ν•„μš”ν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆλ„λ‘ 지원
    1. InitializingBean & DisposableBean μΈν„°νŽ˜μ΄μŠ€

      1
      2
      3
      4
      5
      6
      7
      8
      9
      
       // μ΄ˆκΈ°ν™” λ‹¨κ³„μ—μ„œ μ‹€ν–‰λ˜λŠ” λ©”μ„œλ“œ
       public interface InitializingBean {
       	void afterPropertiesSet() throws Exception;
       }
              
       // μ†Œλ©Έ λ‹¨κ³„μ—μ„œ μ‹€ν–‰λ˜λŠ” λ©”μ„œλ“œ
       public interface DisposableBean {
       	void destroy() throws Exception;
       }
      
      • 빈 객체가 InitialzingBeanκ³Ό DisposableBean μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ β‡’ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλŠ” μ΄ˆκΈ°ν™” κ³Όμ •κ³Ό μ†Œλ©Έ κ³Όμ •μ—μ„œ 각각 빈 객체의 afterPropertiesSet() λ©”μ„œλ“œμ™€ destroy() λ©”μ„œλ“œλ₯Ό μ‹€ν–‰
      • 예제

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        
          public class TestClient implements InitializingBean, DisposableBean {
                    
              private String url;
                    
              public TestClient(String url) {
                  System.out.println("μƒμ„±μž 호좜.");
                  this.url = url;
              }
                    
          		@Override
              public void afterPropertiesSet() throws Exception {
                  System.out.println("μ΄ˆκΈ°ν™” λ©”μ„œλ“œ μ‹€ν–‰.");
              }
                    
              public void connect() {
                  System.out.println("ν΄λΌμ΄μ–ΈνŠΈλ₯Ό " + url + "둜 μ—°κ²°.");
              }
                    
          		@Override
              public void destroy() throws Exception {
                  System.out.println("μ’…λ£Œ λ©”μ„œλ“œ μ‹€ν–‰.");
              }
          }
                    
        
      • but, 문제점 O β‡’ μŠ€ν”„λ§ μ „μš© μΈν„°νŽ˜μ΄μŠ€μ΄κΈ° λ•Œλ¬Έμ—, μ΄ˆκΈ°ν™”μ™€ μ†Œλ©Έ λ©”μ„œλ“œμ˜ 이름을 κ°œλ°œμžκ°€ μž„μ˜λ‘œ λ³€κ²½λΆˆκ°€ / 직접 κ΅¬ν˜„ν•œ ν΄λž˜μŠ€κ°€ μ•„λ‹Œ μ™ΈλΆ€μ—μ„œ 받은 λΌμ΄λΈŒλŸ¬λ¦¬λ‚˜ 클래슀 등에 두 κ°€μ§€ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ μš©ν•  수 μžˆλŠ” 방법이 μ—†μŒ
    2. 문제점 보완, μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” 뢀뢄을 μ‚­μ œ, init()κ³Ό close() λ©”μ„œλ“œ

      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
      32
      33
      34
      35
      
       public class TestClient {
              
           private String url;
              
           public TestClient(String url) {
               System.out.println("μƒμ„±μž 호좜.");
               this.url = url;
           }
              
           public void init() {
               System.out.println("init() μ΄ˆκΈ°ν™” λ©”μ„œλ“œ μ‹€ν–‰.");
           }
              
           public void connect() {
               System.out.println("ν΄λΌμ΄μ–ΈνŠΈλ₯Ό " + url + "둜 μ—°κ²°.");
           }
              
           public void close() {
               System.out.println("close() μ’…λ£Œ λ©”μ„œλ“œ μ‹€ν–‰.");
           }
              
       }
              
       ----------------------------------------------------------------
              
       @Configuration
       public class ClientConfig {
              
           @Bean(initMethod = "init", destroyMethod = "close")
           public TestClient testClient() {
               TestClient testClient = new TestClient("www.naver.com");
               return testClient;
           }
       }
              
      
    3. @PostConstruct와 @PreDestory μ• λ„ˆν…Œμ΄μ…˜μ„ ν™œμš© : μ΅œμ‹  μŠ€ν”„λ§μ—μ„œ κ°€μž₯ ꢌμž₯ν•˜λŠ” 방법

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      
       public class TestClient {
              
           private String url;
              
           public TestClient(String url) {
               System.out.println("μƒμ„±μž 호좜.");
               this.url = url;
           }
              
           @PostConstruct
           public void init() {
               System.out.println("init() μ΄ˆκΈ°ν™” λ©”μ„œλ“œ μ‹€ν–‰.");
           }
              
           public void connect() {
               System.out.println("ν΄λΌμ΄μ–ΈνŠΈλ₯Ό " + url + "둜 μ—°κ²°.");
           }
              
           @PreDestroy
           public void close() {
               System.out.println("close() μ’…λ£Œ λ©”μ„œλ“œ μ‹€ν–‰.");
           }
       }
      
  4. 빈 객체의 관리 λ²”μœ„
    1. 빈 객체의 μŠ€μ½”ν”„λž€ 이름 κ·ΈλŒ€λ‘œ 빈 객체가 μ‘΄μž¬ν•  수 μžˆλŠ” λ²”μœ„λ₯Ό 의미
    2. μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆ μ•ˆμ—μ„œ κ΄€λ¦¬λ˜λŠ” μŠ€ν”„λ§ λΉˆλ„ μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ˜ 생성과 μ’…λ£Œμ™€ ν•¨κ»˜ 운λͺ…을 같이 함
    3. 빈 객체의 관리 λ²”μœ„μ—λŠ” 싱글톀 외에도 ν”„λ‘œν† νƒ€μž…(prototype), μ„Έμ…˜(session), λ¦¬ν€˜μŠ€νŠΈ(request) λ“±μ˜ λ²”μœ„κ°€ 쑴재

      ScopeTest 클래슀

      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
      32
      33
      34
      35
      36
      37
      
       public class ScopeTest {
              
           @Test
           public void scopeTest() {
               // μ»¨ν…Œμ΄λ„ˆ 생성
               AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(TestBean.class);
              
               // μ»¨ν…Œμ΄λ„ˆ μ‚¬μš©
               TestBean bean = annotationConfigApplicationContext.getBean(TestBean.class);
               TestBean bean2 = annotationConfigApplicationContext.getBean(TestBean.class);
              
               System.out.println("bean = " + bean);
               System.out.println("bean2 = " + bean2);
              
               // 검증
               Assertions.assertThat(bean).isSameAs(bean2);
              
               // μ»¨ν…Œμ΄λ„ˆ μ’…λ£Œ
               annotationConfigApplicationContext.close();
           }
              
           static class TestBean {
              
               // μ΄ˆκΈ°ν™” λ©”μ„œλ“œ μ„€μ •
               @PostConstruct
               public void init() {
                   System.out.println("init() μ΄ˆκΈ°ν™” λ©”μ„œλ“œ μ‹€ν–‰.");
               }
              
               // μ’…λ£Œ λ©”μ„œλ“œ μ„€μ •
               @PreDestroy
               public void close() {
                   System.out.println("close() μ’…λ£Œ λ©”μ„œλ“œ μ‹€ν–‰.");
               }
           }
       }
              
      
      • prototype으둜 κ²€μ‚¬ν•˜κ³  μ‹ΆμœΌλ©΄ TestBean 클래슀 μœ„μ— @Scope("prototype") μ• λ„ˆν…Œμ΄μ…˜ 뢙이면 됨.

μ»΄ν¬λ„ŒνŠΈ μŠ€μΊ”κ³Ό μ˜μ‘΄μ„± μžλ™ μ£Όμž…

  1. @Configurationκ³Ό @Bean을 μ‚¬μš©ν•œ μˆ˜λ™ μ£Όμž… 방식
    1. 빈의 μˆ˜κ°€ λ§Žμ„ 경우 λ²ˆκ±°λ‘œμ›€.
  2. μ»΄ν¬λ„ŒνŠΈ μŠ€μΊ” @ComponentScan
    1. μžλ™μœΌλ‘œ μŠ€ν”„λ§ λΉˆμ„ λ“±λ‘ν•˜λŠ” κΈ°λŠ₯, ꡬ체적인 의쑴 관계 섀정이 λΆˆκ°€λŠ₯
    2. λ²”μœ„ λ³€κ²½ν•˜κ³  μ‹ΆμœΌλ©΄ @ComponentScan(basePackages = β€œβ€) μ—μ„œ β€œβ€ 뢀뢄에 νŒ¨ν‚€μ§€ 이름을 ν‘œμ‹œ
    3. @Configuration μ• λ„ˆν…Œμ΄μ…˜,@Controller, @Service, @Repository λ“±μ˜ μ• λ„ˆν…Œμ΄μ…˜λ„ μ»΄ν¬λ„ŒνŠΈ μŠ€μΊ”μ˜ λŒ€μƒμ— 포함
  3. @Autowired μ• λ„ˆν…Œμ΄μ…˜
    1. λΉˆμ„ μžλ™μœΌλ‘œ 등둝함과 λ™μ‹œμ— 의쑴 관계가 μ„€μ •
    2. μƒμ„±μžκ°€ 단 ν•˜λ‚˜λ§Œ μ‘΄μž¬ν•˜λŠ” κ²½μš°μ—λŠ” @Autowired μ• λ„ˆν…Œμ΄μ…˜μ„ 뢙이지 μ•Šμ•„λ„ μžλ™μœΌλ‘œ 의쑴 관계가 μ—°κ²°


### comment

λ„ˆλ¬΄ μ–΄λ ΅λ‹€,, singletonλΆ€ν„°λŠ” 이해가 잘 μ•ˆκ°€μ„œ μ—°νœ΄μ— λ‹€μ‹œ 보고 λ‹€λ₯Έ μžλ£Œλ„ 찾아봐야 ν•  것 κ°™λ‹€
그리고 κ°•μ‚¬λ‹˜μ€ 별말 μ—†μœΌμ‹œκΈ΄ ν–ˆλŠ”λ°β€¦.μ €κΈ° μ‚¬μš©λœ μ½”λ“œλ„ ν•œλ²ˆμ€ 따라 μ³λ³΄λŠ”κ²Œ λ‚«κ²Ÿμ§€? !









Spring μΉ΄ν…Œκ³ λ¦¬ λ‚΄ λ‹€λ₯Έ κΈ€ λ³΄λŸ¬κ°€κΈ°

Leave a comment