์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์™€ ์Šคํ”„๋ง ๋นˆ

2022. 2. 4. 00:33ใ†Backend/๐ŸŒฟ Spring

๊น€์˜ํ•œ ๊ฐ•์‚ฌ๋‹˜์˜ ์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ - ๊ธฐ๋ณธํŽธ ์ˆ˜๊ฐ• ํ›„ ์ •๋ฆฌํ•œ ํฌ์ŠคํŒ…์ž…๋‹ˆ๋‹ค.

 

 

์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ - ๊ธฐ๋ณธํŽธ - ์ธํ”„๋Ÿฐ | ๊ฐ•์˜

์Šคํ”„๋ง ์ž…๋ฌธ์ž๊ฐ€ ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€๋ฉด์„œ ์Šคํ”„๋ง์˜ ํ•ต์‹ฌ ์›๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๊ณ , ์Šคํ”„๋ง ๊ธฐ๋ณธ๊ธฐ๋ฅผ ํ™•์‹คํžˆ ๋‹ค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค., - ๊ฐ•์˜ ์†Œ๊ฐœ | ์ธํ”„๋Ÿฐ...

www.inflearn.com

 

 

1. ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ

ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

ApplicationContext ๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ผ ๋ถ€๋ฅธ๋‹ค. 

๊ธฐ์กด์—๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ AppConfig(์˜ˆ์‹œ) class ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง์ ‘ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  DI ๊นŒ์ง€ ํ–ˆ์ง€๋งŒ, ApplicationContext ๋ฅผ ํ†ตํ•ด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋กœ ์Šคํ”„๋ง ๋นˆ ๊ฐ์ฒด๋ฅผ ์ฐพ๊ณ  DI ๊นŒ์ง€ ํ•œ๋‹ค.

์œ„ ์ฝ”๋“œ์—์„œ AnnotationConfigApplicationContext() ๋ผ๋Š” ๊ตฌํ˜„์ฒด๋ฅผ ํ†ตํ•ด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋งŒ๋“ค๊ณ , ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋Š” ๊ตฌ์„ฑ ์ •๋ณด๋ฅผ ์ง€์ •ํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” AppConfig.class ๋ฅผ ๊ตฌ์„ฑ์ •๋ณด๋กœ ์ง€์ •ํ•œ๋‹ค.

 

์ž ์‹œ AppConfig.class ๋ฅผ ์‚ดํŽด๋ณด์ž

@Bean ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ด ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•  ๊ฐ์ฒด๋ฅผ ํ‘œ์‹œํ•˜๊ณ  ์žˆ๋‹ค. ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ๊ตฌ์„ฑ์ •๋ณด๋กœ AppConfig.class ๋ฅผ ์ง€์ •ํ•˜๋ฉด, @Bean ์œผ๋กœ ์ง€์ •๋œ ๊ฐ์ฒด๋“ค์ด ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋œ๋‹ค.

@Configuration
public class AppConfig {

    @Bean
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public OrderService orderService() {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

    @Bean
    public DiscountPolicy discountPolicy() {
        return new RateDiscountPolicy();
    }
}

* ์Šคํ”„๋ง์€ ๋นˆ์„ ์ƒ์„ฑํ•˜๊ณ  ์˜์กด๊ด€๊ณ„๋ฅผ ์ฃผ์ž…ํ•˜๋Š” ๋‹จ๊ณ„๊ฐ€ ๋‚˜๋ˆ„์–ด์ ธ ์žˆ๋‹ค.
 
 

์Šคํ”„๋ง ๋นˆ์€ ๋ฌด์—‡์ธ๊ฐ€?

Spring Container ๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ์ž๋ฐ” ๊ฐ์ฒด๋ฅผ Bean ์ด๋ผ ๋ถ€๋ฅธ๋‹ค.

์œ„ ์ฝ”๋“œ์—์„œ AnnotationConfigApplicationContext() ๋ผ๋Š” ๊ตฌํ˜„์ฒด๋ฅผ ํ†ตํ•ด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋งŒ๋“ ๋‹ค.

 

2. ์Šคํ”„๋ง ๋นˆ ์กฐํšŒ

์œ„ ๊ทธ๋ฆผ์—์„œ ๋นˆ ์ด๋ฆ„์— ์„œ๋กœ ๋‹ค๋ฅธ 4๊ฐ€์ง€  ๋นˆ์ด ๋“ฑ๋ก๋œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๊ฐ๊ฐ์˜ ๋นˆ์˜ ํƒ€์ž…์€ MemberService, OrderService, MemberRepository, DiscountPolicy ์ด๋‹ค. ๋งŒ์•ฝ ์ด๋ฆ„์€ ๋‹ค๋ฅด์ง€๋งŒ ๋™์ผํ•œ ํƒ€์ž…์˜ ๋นˆ์ด ๋“ฑ๋ก๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ?

NoUniqueBeanDefinitionException ์ด๋ผ๋Š” ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ๋™์ผํ•œ ํƒ€์ž…์˜ ๋นˆ์€ 2๊ฐœ ์ด์ƒ ์กด์žฌํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์ผ๊นŒ?

๊ทธ๋ ‡์ง€ ์•Š๋‹ค. ์œ„ ๊ทธ๋ฆผ์—์„œ ๋นˆ ์ด๋ฆ„ ์ปฌ๋Ÿผ์ด ์žˆ๋“ฏ์ด, ๊ฐ์ž์˜ ๋นˆ์€ ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด์ด๊ธฐ์— ์ด๋ฆ„์„ ์ง€์ •ํ•˜์—ฌ ๊ฐœ๋ณ„๋กœ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

3. ์Šคํ”„๋ง ๋นˆ ์ƒ์† ๊ด€๊ณ„

์Šคํ”„๋ง์—์„   ๋ถ€๋ชจํƒ€์ž…์œผ๋กœ ๋นˆ์„ ์กฐํšŒํ•˜๋ฉด ์ž์‹ ํƒ€์ž…๋„ ํ•จ๊ป˜ ์กฐํšŒ๋œ๋‹ค.

๊ทธ๋ž˜์„œ ๋ชจ๋“  ์ž๋ฐ” ๊ฐ์ฒด์˜ ์ตœ๊ณ  ๋ถ€๋ชจ์ธ Object ํƒ€์ž…์œผ๋กœ ์กฐํšŒํ•˜๋ฉด, ๋ชจ๋“  ์Šคํ”„๋ง ๋นˆ์„ ์กฐํšŒํ•œ๋‹ค.

 

public class ApplicationContextExtendsFindTest {
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
 
    @Test
    @DisplayName("๋ถ€๋ชจ ํƒ€์ž…์œผ๋กœ ์กฐํšŒ์‹œ, ์ž์‹์ด ๋‘˜ ์ด์ƒ ์žˆ์œผ๋ฉด, ์ค‘๋ณต ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค")
    void findBeanByParentTypeDuplicate(){
        Assertions.assertThrows(NoUniqueBeanDefinitionException.class, () -> ac.getBean(DiscountPolicy.class));
    }
 
 
    @Test
    @DisplayName("๋ถ€๋ชจ ํƒ€์ž…์œผ๋กœ ์กฐํšŒ์‹œ, ์ž์‹์ด ๋‘˜ ์ด์ƒ ์žˆ์œผ๋ฉด, ๋นˆ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๋ฉด ๋œ๋‹ค.")
    void findBeanByParentTypeBeanName(){
        RateDiscountPolicy rateDiscountPolicy = ac.getBean("rateDiscountPolicy", RateDiscountPolicy.class);
        assertThat(rateDiscountPolicy).isInstanceOf(RateDiscountPolicy.class);
    }
 
    @Test
    @DisplayName("๋ถ€๋ชจ ํƒ€์ž…์œผ๋กœ ๋ชจ๋‘ ์กฐํšŒํ•˜๊ธฐ")
    void findAllBeanByParentType() {
        Map<String, DiscountPolicy> beansOfType = ac.getBeansOfType(DiscountPolicy.class);
        assertThat(beansOfType.size()).isEqualTo(2);
 
        // ์‹ค์ œ ํ…Œ์ŠคํŠธ์ฝ”๋“œ ์ž‘์„ฑํ•  ๋•Œ๋Š” ์ด๋ ‡๊ฒŒ ๋ฐ˜๋ณต๋ฌธ์ด๋‚˜ println ์€ ๋‚จ๊ฒจ๋‘๋Š” ๊ฒƒ์€ ์ ์ ˆํ•˜์ง€ ์•Š๋‹ค. ํ…Œ์ŠคํŠธ ์‹œ์Šคํ…œ์ด ํŒ๋ณ„ํ•˜๊ฒŒ ํ•ด์•ผํ•˜์ง€, ์•„๋ž˜ ๊ฐ™์€ ๋ฐ˜๋ณต๋ฌธ์€ ์‚ฌ๋žŒ์˜ ๋ˆˆ์œผ๋กœ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ.
        for (String key : beansOfType.keySet()) {
            System.out.println("key = " + key + " value = " + beansOfType.get(key));
        }
    }
 
    @Test
    @DisplayName("๋ถ€๋ชจ ํƒ€์ž…์œผ๋กœ ๋ชจ๋‘ ์กฐํšŒํ•˜๊ธฐ - Object")
    void findAllBeanByObjectType() {
        Map<String, Object> beansOfType = ac.getBeansOfType(Object.class);
        for (String key : beansOfType.keySet()) {
            System.out.println("key = " + key + " value = " + beansOfType.get(key));
        }
    // ์œ„์—์„œ ํ…Œ์ŠคํŠธํ•œ ๋นˆ์€ ๋ฌผ๋ก , spring ์— ์žˆ๋Š” ๋นˆ๊นŒ์ง€ ๋ชจ๋‘ ํŠ€์–ด๋‚˜์˜จ๋‹ค. => java ๋Š” ๋ชจ๋“ ๊ฒŒ Object ๋ฅผ ์ƒ์†๋ฐ›๊ธฐ ๋•Œ๋ฌธ.        
    }  
 
      // AppConfig.class ์ˆ˜์ • ๋Œ€์‹ , ์ž„์‹œ config ํด๋ž˜์Šค ์ž‘์„ฑ
    @Configuration
    static class TestConfig {
        @Bean
        public DiscountPolicy rateDiscountPolicy() {
            return new RateDiscountPolicy();
        }
 
        @Bean
        public DiscountPolicy fixDiscountPolicy() {
            return new FixDiscountPolicy();
        }
    }
}

์‹ค์ œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ๋•, ์ด๋Ÿฐ ์‹์œผ๋กœ ApplicationContext  ๋กœ ๋นˆ์„ ์กฐํšŒํ•  ์ผ์€ ๊ฑฐ์˜ ์—†์ง€๋งŒ, ๋ถ€๋ชจ ํƒ€์ž…์œผ๋กœ ์กฐํšŒํ•  ๋•Œ ์–ด๋””๊นŒ์ง€ ์กฐํšŒ๋˜๋Š”์ง€ ๋“ฑ์˜ ๋‚ด์šฉ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ˆ™์ง€ํ•ด์•ผ ํ•˜๋Š” ๊ฐœ๋…์ด๋‹ค.

 

 

4. BeanFactory ์™€ ApplicationContext

์•ž์„œ ApplicationContext ๊ฐ€ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ผ ์†Œ๊ฐœํ–ˆ๋Š”๋ฐ, ApplicationContext ๋„ ๊ฒฐ๊ตญ์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฉฐ ๋™์‹œ์— BeanFactory ๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†๋ฐ›๊ณ  ์žˆ๋‹ค. 

 

[ BeanFactory ]

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์ตœ์ƒ์œ„ ์ธํ„ฐํŽ˜์ด์Šค๋‹ค.
์Šคํ”„๋ง ๋นˆ์„ ๊ด€๋ฆฌํ•˜๊ณ  ์กฐํšŒํ•˜๋Š” ์—ญํ• ์„ ๋‹ด๋‹นํ•œ๋‹ค. ( getBean() ์„ ์ œ๊ณต )
์ง€๊ธˆ๊นŒ์ง€ ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ–ˆ๋˜ ๋Œ€๋ถ€๋ถ„์˜ ๊ธฐ๋Šฅ์€ BeanFactory๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค

BeanFactory ๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•  ์ผ์€ ๊ฑฐ์˜ ์—†๊ณ , ๋Œ€์‹  ๋ถ€๊ฐ€๊ธฐ๋Šฅ์ด ํฌํ•จ๋œ ApplicationContext ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

 

[ ApplicationContext ]

BeanFactory ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ ์ƒ์†๋ฐ›์•„์„œ ์ œ๊ณตํ•œ๋‹ค.


๋นˆ์„ ๊ด€๋ฆฌํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•˜๋Š” ๊ธฐ๋Šฅ์„ BeanFactory๊ฐ€ ์ œ๊ณตํ•ด์ฃผ๋Š”๋ฐ, ๊ทธ๋Ÿฌ๋ฉด ๋‘˜์˜ ์ฐจ์ด๊ฐ€ ๋ญ˜๊นŒ?
์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ๋•Œ๋Š” ๋นˆ์€ ๊ด€๋ฆฌํ•˜๊ณ  ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ์€ ๋ฌผ๋ก ์ด๊ณ , ์ˆ˜ ๋งŽ์€ ๋ถ€๊ฐ€๊ธฐ๋Šฅ์ด ํ•„์š”ํ•˜๋‹ค

๊ทธ ์ค‘์—๋Š” ๋ฉ”์‹œ์ง€ ์†Œ์Šค๋ฅผ ํ™œ์šฉํ•œ ๊ตญ์ œํ™” ๊ธฐ๋Šฅ , ํ™˜๊ฒฝ๋ณ€์ˆ˜, ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ด๋ฒคํŠธ , ํŽธ๋ฆฌํ•œ ๋ฆฌ์†Œ์Šค ์กฐํšŒ ๋“ฑ์˜ ๋‹ค์–‘ํ•œ ๋ถ€๊ฐ€๊ธฐ๋Šฅ์ด ์กด์žฌํ•œ๋‹ค.

 

BeanFactory ๋‚˜ ApplicationContext ๋ชจ๋‘ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ผ ๋ถ€๋ฅธ๋‹ค.

 

 

5. ์Šคํ”„๋ง ๋นˆ ์„ค์ • ๋ฉ”ํƒ€ ์ •๋ณด - BeanDefinition

์Šคํ”„๋ง์˜ ์„ค์ • ํ˜•์‹์—๋Š” xml ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ๋™์‹œ์— ์ž๋ฐ” ์ฝ”๋“œ๋ฅผ ์ด์šฉํ•˜๋Š” ๋ฐฉ์‹์ด ์กด์žฌํ•œ๋‹ค.

์–ด๋–ป๊ฒŒ ์ด๋Ÿฐ ๋‹ค์–‘ํ•œ ์„ค์ • ํ˜•์‹์„ ์ง€์›ํ•  ์ˆ˜ ์žˆ์„๊นŒ? ๊ทธ ์ค‘์‹ฌ์—๋Š” BeanDefinition ์ด๋ผ๋Š” ์ถ”์ƒํ™”๊ฐ€ ์กด์žฌํ•œ๋‹ค.

์ฆ‰ ์—ญํ• ๊ณผ ๊ตฌํ˜„์„ ๊ฐœ๋…์ ์œผ๋กœ ๋‚˜๋ˆˆ ๊ฒƒ์ด๋‹ค.

Annotated ๋ผ๋Š” ๋ถ€๋ถ„์€, ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ๋นˆ์„ ์ƒ์„ฑํ•œ ๊ฒƒ์œผ๋กœ @Bean ์„ ์‚ฌ์šฉํ•œ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

๊ทธ ๋‹ค์Œ์— ๋‚˜์˜ค๋Š” Xml ๋ถ€๋ถ„์€ Xml  ํŒŒ์ผ๋กœ ์Šคํ”„๋ง ๋นˆ์„ ์„ค์ •ํ•œ ํ˜•์‹์„ ๋‚˜ํƒ€๋‚ธ๋‹ค. 

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ƒˆ๋กœ์šด ํ˜•์‹์˜ ์„ค์ • ์ •๋ณด๊ฐ€ ์ถ”๊ฐ€๋˜๋ฉด(์–ด๋…ธํ…Œ์ด์…˜๋„, xml ๋„ ์•„๋‹Œ) XxxBeanDefinitionReader ๋ฅผ ๋งŒ๋“ค์–ด BeanDefinition ์„ ์ƒ์„ฑํ•˜๋ฉด ๋œ๋‹ค.