Super Kawaii Cute Cat Kaoani
๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
{Back-end}/SpringBoot

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

by wonee1 2025. 9. 10.
728x90

๐Ÿ–Š๏ธ ๋ณธ ํฌ์ŠคํŠธ๋Š” ์ธํ”„๋Ÿฐ ๊น€์˜ํ•œ ์Šคํ”„๋ง ๊ธฐ๋ณธํŽธ์„ ๋ณด๊ณ  ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. 

 

 

 

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

ํ˜„์žฌ ํ‰์  5.0์  ์ˆ˜๊ฐ•์ƒ 48,207๋ช…์ธ ๊ฐ•์˜๋ฅผ ๋งŒ๋‚˜๋ณด์„ธ์š”. ์Šคํ”„๋ง ์ž…๋ฌธ์ž๊ฐ€ ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€๋ฉด์„œ ์Šคํ”„๋ง์˜ ํ•ต์‹ฌ ์›๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๊ณ , ์Šคํ”„๋ง ๊ธฐ๋ณธ๊ธฐ๋ฅผ ํ™•์‹คํžˆ ๋‹ค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์Šคํ”„๋ง ๊ธฐ๋ณธ ๊ธฐ๋Šฅ, ์Šคํ”„

www.inflearn.com

 

 

 

 

 

 

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

 

 //์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

 

 

ApplicationContext 

 

  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ผ๊ณ  ํ•˜๋ฉฐ ์ธํ„ฐํŽ˜์ด์Šค๋‹ค.
  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” xml์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ณ  ์–ด๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜์˜ ์ž๋ฐ” ์„ค์ • ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” @Component, @Configuration, @Bean ๊ฐ™์€ ์• ๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ํด๋ž˜์Šค๋ฅผ ์ฝ์–ด์„œ, ํ•„์š”ํ•œ ๊ฐ์ฒด๋“ค(๋นˆ, Bean)์„ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋ฉฐ, ๊ฐ์ฒด๋“ค ๊ฐ„์˜ ์˜์กด๊ด€๊ณ„๋ฅผ ์ž๋™์œผ๋กœ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค. 

 

์ง์ „ ์‹ค์Šต์—์„œ AppConfig.๋ฅผ ์‚ฌ์šฉํ–ˆ๋˜ ๋ฐฉ์‹์ด ์–ด๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜์˜ ์ž๋ฐ” ์„ค์ • ํด๋ž˜์Šค๋กœ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋งŒ๋“  ๊ฒƒ 

 

 

 

 

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์ƒ์„ฑ ๊ณผ์ • 

 

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

 

'

 

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

 

2. ์Šคํ”„๋ง ๋นˆ ๋“ฑ๋ก 

 

 

  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜์–ด์˜จ ์„ค์ • ํด๋ž˜์Šค ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์Šคํ”„๋ง ๋นˆ์„ ๋“ฑ๋กํ•œ๋‹ค 
  • @Bean ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์€ ๋ฉ”์„œ๋“œ๋Š” ์Šคํ”„๋ง ๋นˆ์„ ๋“ฑ๋กํ•˜๋Š” ๋ฉ”์„œ๋“œ๋กœ ์ธ์‹ํ•œ๋‹ค. 
  • ์—ฌ๊ธฐ์„œ @x01, @x02๋Š” ๋‹จ์ˆœํžˆ ๊ฐ์ฒด์˜ ๋ฉ”๋ชจ๋ฆฌ ์œ„์น˜(์ฃผ์†Œ๊ฐ’)๋ฅผ ํ‘œํ˜„ํ•œ ๊ฒƒ

 

 

 

โš ๏ธ์ฃผ์˜

 

๋นˆ ์ด๋ฆ„์€ ํ•ญ์ƒ ๋‹ค๋ฅธ ์ด๋ฆ„์„ ๋ถ€์—ฌํ•ด์•ผํ•œ๋‹ค
๋™์ผํ•œ ์ด๋ฆ„์˜ ๋นˆ์ด ๋“ฑ๋ก๋˜๋ฉด ๊ธฐ์กด ๋นˆ์„ ๋ฎ์–ด์“ฐ๊ฑฐ๋‚˜(BeanDefinitionOverride), ์ถฉ๋Œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

3. ์Šคํ”„๋ง ๋นˆ ์˜์กด๊ด€๊ณ„ ์„ค์ • - ์ค€๋น„

 

 

 

 

  • memberService๋ฅผ ์ƒ์„ฑํ•  ๋•Œ memberRepository() ํ•„์š”
  • orderService๋ฅผ ์ƒ์„ฑํ•  ๋•Œ memberRepository(), discountPolicy() ํ•„์š”

 

 

 

4. ์Šคํ”„๋ง ๋นˆ ์˜์กด๊ด€๊ณ„ ์„ค์ • - ์™„๋ฃŒ 

 

 

 

 

 

  • ์ด์ œ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ AppConfig ์„ค์ • ์ •๋ณด๋ฅผ ์ด์šฉํ•ด ์‹ค์ œ ์˜์กด์„ฑ์„ ์ฃผ์ž…(DI, Dependency Injection)ํ•œ๋‹ค
  • ๊ฐ ์„œ๋น„์Šค๊ฐ€ ํ•„์š”๋กœ ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ฐพ์•„์„œ ์ž๋™์œผ๋กœ ์—ฐ๊ฒฐํ•ด ์ค€๋‹ค. 

 

 

 

 

์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋œ ๋ชจ๋“  ๋นˆ ์กฐํšŒ


 

 

 

package hello.core.beanfind;
import hello.core.AppConfig;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;

class ApplicationContextInfoTest {
    AnnotationConfigApplicationContext ac = new
            AnnotationConfigApplicationContext(AppConfig.class); // 1. ์ปจํ…Œ์ด๋„ˆ ์ƒ์„ฑ 
    @Test
    @DisplayName("๋ชจ๋“  ๋นˆ ์ถœ๋ ฅํ•˜๊ธฐ") 
    void findAllBean() {  //2. ๋ชจ๋“  ๋นˆ ์ถœ๋ ฅํ•˜๊ธฐ
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            Object bean = ac.getBean(beanDefinitionName);
            System.out.println("name=" + beanDefinitionName + " object=" +
                    bean);
        }
    }
    @Test
    @DisplayName("์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋นˆ ์ถœ๋ ฅํ•˜๊ธฐ")
    void findApplicationBean() { //3. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋นˆ ์ถœ๋ ฅํ•˜๊ธฐ 
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            BeanDefinition beanDefinition =
                    ac.getBeanDefinition(beanDefinitionName);

            //Role ROLE_APPLICATION: ์ง์ ‘ ๋“ฑ๋กํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋นˆ
            //Role ROLE_INFRASTRUCTURE: ์Šคํ”„๋ง์ด ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋นˆ
            if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
                Object bean = ac.getBean(beanDefinitionName);
                System.out.println("name=" + beanDefinitionName + " object=" + bean);



            }
        }
    }
}

 

 

๋ชจ๋“  ๋นˆ์ถœ๋ ฅํ•˜๊ธฐ  

 

  • ac.getBeanDefinitionNames() → ํ˜„์žฌ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋œ ๋ชจ๋“  ๋นˆ ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜จ๋‹ค. 
  • ac.getBean(beanDefinitionName) → ํ•ด๋‹น ๋นˆ ์ด๋ฆ„์œผ๋กœ ์‹ค์ œ ๋นˆ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
  • ๋”ฐ๋ผ์„œ ์‹คํ–‰ ๊ฒฐ๊ณผ๋Š” ๋‚ด๊ฐ€ ๋“ฑ๋กํ•œ ๋นˆ + ์Šคํ”„๋ง ๋‚ด๋ถ€์—์„œ ๋“ฑ๋กํ•œ ๋นˆ๊นŒ์ง€ ๋ชจ๋‘ ์ถœ๋ ฅ๋œ๋‹ค

 

 

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋นˆ ์ถœ๋ ฅํ•˜๊ธฐ

 

  • BeanDefinition ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ๋นˆ์˜ ์—ญํ• (Role)์„ ํ™•์ธํ•œ๋‹ค.
  • ์Šคํ”„๋ง ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋นˆ์€ getRole() ๊ฐ’์œผ๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค 
    • ROLE_APPLICATION → ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๋“ฑ๋กํ•œ ๋นˆ (AppConfig์—์„œ ๋งŒ๋“  ๊ฒƒ๋“ค)
    • ROLE_INFRASTRUCTURE → ์Šคํ”„๋ง ๋‚ด๋ถ€ ๋™์ž‘์„ ์œ„ํ•ด ๋“ฑ๋ก๋œ ๋นˆ (์˜ˆ: ์ž๋™ ํ”„๋ก์‹œ ์ƒ์„ฑ๊ธฐ ๋“ฑ)
  • ๋”ฐ๋ผ์„œ ์‹คํ–‰๊ฒฐ๊ณผ๋Š” ๋‚ด๊ฐ€ ๋“ฑ๋กํ•œ ๋นˆ๋งŒ ์ถœ๋ ฅ๋œ๋‹ค

 

 

์‹คํ–‰๊ฒฐ๊ณผ 

๋”๋ณด๊ธฐ
Starting Gradle Daemon...
Gradle Daemon started in 1 s 398 ms
> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :compileTestJava
> Task :processTestResources NO-SOURCE
> Task :testClasses
name=appConfig object=hello.core.AppConfig$$SpringCGLIB$$0@70e659aa
name=memberService object=hello.core.member.MemberServiceImpl@2ef8a8c3
name=orderService object=hello.core.order.OrderServiceImpl@24f43aa3
name=memberRepository object=hello.core.member.MemoryMemberRepository@63fd4873
name=discountPolicy object=hello.core.discount.RateDiscountPolicy@1e11bc55
name=org.springframework.context.annotation.internalConfigurationAnnotationProcessor object=org.springframework.context.annotation.ConfigurationClassPostProcessor@77b21474
name=org.springframework.context.annotation.internalAutowiredAnnotationProcessor object=org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@52d10fb8
name=org.springframework.context.annotation.internalCommonAnnotationProcessor object=org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@41c07648
name=org.springframework.context.event.internalEventListenerProcessor object=org.springframework.context.event.EventListenerMethodProcessor@1fe8d51b
name=org.springframework.context.event.internalEventListenerFactory object=org.springframework.context.event.DefaultEventListenerFactory@781e7326
name=appConfig object=hello.core.AppConfig$$SpringCGLIB$$0@22680f52
name=memberService object=hello.core.member.MemberServiceImpl@60d84f61
name=orderService object=hello.core.order.OrderServiceImpl@39c11e6c
name=memberRepository object=hello.core.member.MemoryMemberRepository@324dcd31
name=discountPolicy object=hello.core.discount.RateDiscountPolicy@503d56b5
> Task :test
BUILD SUCCESSFUL in 10s

 

 

 

์Šคํ”„๋ง ๋นˆ ์กฐํšŒ - ๊ธฐ๋ณธ


 

์Šคํ”„๋ง ๋นˆ ์กฐํšŒ ๊ธฐ๋ณธ ๋ฐฉ๋ฒ• 

 

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ ์Šคํ”„๋ง ๋นˆ์„ ์ฐพ๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ์กฐํšŒ ๋ฐฉ๋ฒ•

  • ac.getBean(๋นˆ์ด๋ฆ„, ํƒ€์ž…)
  • ac.getBean(ํƒ€์ž…)

 

 

 

1. ๋นˆ ์ด๋ฆ„ + ํƒ€์ž…์œผ๋กœ ์กฐํšŒ

MemberService memberService = ac.getBean("memberService", MemberService.class);

 

  • "memberService" → ์Šคํ”„๋ง ๋นˆ ์ด๋ฆ„ (๋ฉ”์„œ๋“œ ์ด๋ฆ„์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ๋นˆ ์ด๋ฆ„์ด ๋จ)
  • MemberService.class → ๋นˆ์˜ ํƒ€์ž…
  • ์žฅ์ : ๋™์ผ ํƒ€์ž…์˜ ๋นˆ์ด ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ์–ด๋„, ์ด๋ฆ„์œผ๋กœ ๊ตฌ๋ถ„ ๊ฐ€๋Šฅ
  • ๋‹จ์ : ์ด๋ฆ„์ด ํ‹€๋ฆฌ๋ฉด NoSuchBeanDefinitionException ๋ฐœ์ƒ

 

 

 

2. ํƒ€์ž…์œผ๋กœ๋งŒ์กฐํšŒ  

 

MemberService memberService = ac.getBean(MemberService.class);

 

  • ๋นˆ ์ด๋ฆ„์„ ์ƒ๋žตํ•˜๊ณ  ํƒ€์ž…๋งŒ์œผ๋กœ ์กฐํšŒ ๊ฐ€๋Šฅ
  • ๊ฐ™์€ ํƒ€์ž…์˜ ๋นˆ์ด ํ•˜๋‚˜๋งŒ ์žˆ์„ ๋•Œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • ๊ฐ™์€ ํƒ€์ž…์˜ ๋นˆ์ด ๋‘˜ ์ด์ƒ ์žˆ์œผ๋ฉด NoUniqueBeanDefinitionException ๋ฐœ์ƒ

 

 

 

3. ์กฐํšŒ ๋Œ€์ƒ ์Šคํ”„๋ง ๋นˆ์ด ์—†์œผ๋ฉด? 

 

 

   ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค 

NoSuchBeanDefinitionException: No bean named 'xxxxx' available

 

 

 

 

 

 

 

์‹ค์Šต ์˜ˆ์ œ ์ฝ”๋“œ 

package hello.core.beanfind;
import hello.core.AppConfig;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.assertj.core.api.Assertions.*;

class ApplicationContextBasicFindTest {

    AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(AppConfig.class);

    @Test
    @DisplayName("๋นˆ ์ด๋ฆ„์œผ๋กœ ์กฐํšŒ")
    void findBeanByName(){
        MemberService memberService=ac.getBean("memberService",MemberService.class);
        assertThat(memberService).isInstanceOf(MemberServiceImpl.class); //memberService ๊ฐ์ฒด๊ฐ€ MemberServiceImpl ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์ธ์ง€ ํ™•์ธ
    }



    @Test
    @DisplayName("์ด๋ฆ„ ์—†์ด ํƒ€์ž…๋งŒ์œผ๋กœ ์กฐํšŒ")
    void findBeanByType(){
        MemberService memberService=ac.getBean("memberService",MemberService.class);
        assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
    }

    @Test
    @DisplayName("๊ตฌ์ฒด ํƒ€์ž…์œผ๋กœ ์กฐํšŒ")
    void findBeanByName2() {
        MemberServiceImpl memberService = ac.getBean("memberService",
                MemberServiceImpl.class);
        assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
    }

    @Test
    @DisplayName("๋นˆ ์ด๋ฆ„์œผ๋กœ ์กฐํšŒ X")
    void findBeanByNameX(){
        //ac.getBean("xxxxx", MemberService.class);
        Assertions.assertThrows(NoSuchBeanDefinitionException.class,() -> ac.getBean("xxxxx",MemberService.class));
    }

}

 

 

 

ac.getBean(...) 

  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ ๋นˆ์„ ๊บผ๋‚ด์˜ค๋Š” ๋ฉ”์„œ๋“œ

 

 

assertThat(...)

  • AssertJ๋ผ๋Š” ํ…Œ์ŠคํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ฉ”์„œ๋“œ.
  • JUnit๊ณผ ํ•จ๊ป˜ ์ž์ฃผ ์“ฐ์ž„.

 

.isInstanceOf(MemberServiceImpl.class)

  • memberService ๊ฐ์ฒด๊ฐ€ MemberServiceImpl ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์ธ์ง€ ํ™•์ธ.
  • (์ฆ‰, memberService๊ฐ€ ์ •๋ง ๊ตฌํ˜„์ฒด MemberServiceImpl๋กœ ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ๊ฒ€์ฆํ•˜๋Š” ๊ฒƒ)

 

ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ  ์กฐํšŒ ๊ธฐ์ค€  ๋ฐ˜ํ™˜ ํƒ€์ž… ์กฐํšŒ ๋ฐฉ์‹
findBeanByName "memberService" + MemberService.class MemberService ์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž… ์กฐํšŒ
findBeanByType MemberService.class MemberService ์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž… ์กฐํšŒ
findBeanByName2 "memberService" + MemberServiceImpl.class MemberServiceImpl ๊ตฌ์ฒด ํƒ€์ž… ์กฐํšŒ

 

 

์ฐธ๊ณ 

๊ตฌ์ฒด ํƒ€์ž…์œผ๋กœ ์กฐํšŒํ•˜๋ฉด ๋ณ€๊ฒฝ์‹œ ์œ ์—ฐ์„ฑ์ด ๋–จ์–ด์ง„๋‹ค.

 

 

 

 

 

์Šคํ”„๋ง ๋นˆ ์กฐํšŒ - ๋™์ผํ•œ ํƒ€์ž…์ด ๋‘˜ ์ด์ƒ 


 

ํƒ€์ž…์œผ๋กœ ์กฐํšŒ ์‹œ ๊ฐ™์€ ํƒ€์ž…์˜ ์Šคํ”„๋ง ๋นˆ์ด ๋‘˜ ์ด์ƒ์ด๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒ -> ์ด๋•Œ ๋นˆ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๋ฉด๋œ๋‹ค 

 

 

ac.getBeansOfType()์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•ด๋‹น ํƒ€์ž…์˜ ๋ชจ๋“  ๋นˆ์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค 

 

 

 

public class ApplicationContextSameBeanFindTest {

    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);

    @Test
    @DisplayName("ํƒ€์ž…์œผ๋กœ ์กฐํšŒ์‹œ ๊ฐ™์€ ํƒ€์ž…์ด ๋‘˜ ์ด์ƒ ์žˆ์œผ๋ฉด, ์ค‘๋ณต ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค")
    void findBeanByTypeDuplicate() {
        //MemberRepository bean = ac.getBean(MemberRepository.class);
        assertThrows(NoUniqueBeanDefinitionException.class, () ->
                ac.getBean(MemberRepository.class));
    }

    @Test
    @DisplayName("ํƒ€์ž…์œผ๋กœ ์กฐํšŒ์‹œ ๊ฐ™์€ ํƒ€์ž…์ด ๋‘˜ ์ด์ƒ ์žˆ์œผ๋ฉด, ๋นˆ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๋ฉด ๋œ๋‹ค")
    void findBeanByName() {
        MemberRepository memberRepository = ac.getBean("memberRepository1", MemberRepository.class);
        assertThat(memberRepository).isInstanceOf(MemberRepository.class);
    }

    @Test
    @DisplayName("ํŠน์ • ํƒ€์ž…์„ ๋ชจ๋‘ ์กฐํšŒํ•˜๊ธฐ")
    void findAllBeanByType() {
        Map<String, MemberRepository> beansOfType = ac.getBeansOfType(MemberRepository.class);
        for (String key : beansOfType.keySet()) {
            System.out.println("key = " + key + " value = " +
                    beansOfType.get(key));
        }
        System.out.println("beansOfType = " + beansOfType);
        assertThat(beansOfType.size()).isEqualTo(2);
    }

    @Configuration
    static class SameBeanConfig {
        
        @Bean
        public MemberRepository memberRepository1() {
            return new MemoryMemberRepository();
        }
        
        @Bean
        public MemberRepository memberRepository2() {
            return new MemoryMemberRepository();   
        }


    }

}

 

 

Map<String, MemberRepository>

  • key → ๋นˆ ์ด๋ฆ„ ("memberRepository1", "memberRepository2" ๋“ฑ)
  • value → ๋นˆ ๊ฐ์ฒด (MemoryMemberRepository, JdbcMemberRepository ๊ฐ™์€ ๊ตฌํ˜„์ฒด ์ธ์Šคํ„ด์Šค)

 

@Configuration  ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋นˆ์„ ๋“ฑ๋กํ•˜๊ธฐ ์œ„ํ•œ ์„ค์ • ํด๋ž˜์Šค์ž„์„ ํ‘œ์‹œํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜

 

 

 

์‹คํ–‰๊ฒฐ๊ณผ 

๋”๋ณด๊ธฐ
> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :compileTestJava
> Task :processTestResources NO-SOURCE
> Task :testClasses
key = memberRepository1 value = hello.core.member.MemoryMemberRepository@41c07648
key = memberRepository2 value = hello.core.member.MemoryMemberRepository@2d35442b
beansOfType = {memberRepository1=hello.core.member.MemoryMemberRepository@41c07648, memberRepository2=hello.core.member.MemoryMemberRepository@2d35442b}
> Task :test
BUILD SUCCESSFUL in 3s
4 actionable tasks: 2 executed, 2 up-to-date
์˜คํ›„ 8:54:12: Execution finished ':test --tests "hello.core.beanfind.ApplicationContextSameBeanFindTest"'.

 

 

 

์Šคํ”„๋ง ๋นˆ ์กฐํšŒ - ์ƒ์† ๊ด€๊ณ„ 


 

 

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

 

 

   @Test
    @DisplayName("๋ถ€๋ชจ ํƒ€์ž…์œผ๋กœ ๋ชจ๋‘ ์กฐํšŒํ•˜๊ธฐ")
    void findAllBeanByParentType() {
        Map<String, DiscountPolicy> beansOfType =
                ac.getBeansOfType(DiscountPolicy.class);
        assertThat(beansOfType.size()).isEqualTo(2);
        for (String key : beansOfType.keySet()) {
            System.out.println("key = " + key + " value=" +
                    beansOfType.get(key));
        }
    }

 

ac.getBeansOfType(DiscountPolicy.class)

  • DiscountPolicy๋Š” ์ธํ„ฐํŽ˜์ด์Šค (๋ถ€๋ชจ ํƒ€์ž…).
  • ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋œ DiscountPolicy๋ฅผ ๊ตฌํ˜„ํ•œ ๋ชจ๋“  ๋นˆ์„ Map์œผ๋กœ ๋ฐ˜ํ™˜.

 assertThat(beansOfType.size()).isEqualTo(2);

  • ์ปจํ…Œ์ด๋„ˆ์— DiscountPolicy ๊ตฌํ˜„์ฒด ๋นˆ์ด 2๊ฐœ ๋“ฑ๋ก๋˜์–ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋Š” ํ…Œ์ŠคํŠธ.
  • ๋ณดํ†ต AppConfig ๊ฐ™์€ ์„ค์ • ํด๋ž˜์Šค์— ์ด๋ ‡๊ฒŒ ๋“ฑ๋กํ•ด๋‘”๋‹ค. 

 

์ •๋ฆฌ 

 

  • ๋ถ€๋ชจ ํƒ€์ž…(DiscountPolicy)์œผ๋กœ ์กฐํšŒํ•˜๋ฉด, ์ž์‹ ํƒ€์ž…(RateDiscountPolicy, FixDiscountPolicy) ๋นˆ์ด ๋ชจ๋‘ ์กฐํšŒ๋œ๋‹ค.
  • ac.getBeansOfType(๋ถ€๋ชจํƒ€์ž…) → ๋ฐ˜ํ™˜: Map<String, ๋ถ€๋ชจํƒ€์ž…>
  • ์ด ๋ฐฉ์‹์œผ๋กœ ๋‹คํ˜•์„ฑ์„ ํ™œ์šฉํ•œ ๋นˆ ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

 

 

 

BeanFactory์™€ ApplicationContext


 

 

 

 

BeanFactory

 

1. ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์ตœ์ƒ์œ„ ์ธํ„ฐํŽ˜์ด์Šค๋‹ค.

2. ์Šคํ”„๋ง ๋นˆ์„ ๊ด€๋ฆฌํ•˜๊ณ  ์กฐํšŒํ•˜๋Š” ์—ญํ• ์„ ๋‹ด๋‹นํ•œ๋‹ค.

 

 

  • ๋นˆ ๊ด€๋ฆฌ (Bean Lifecycle ๊ด€๋ฆฌ)
    • @Bean์ด๋‚˜ @Component๋กœ ์ •์˜๋œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ปจํ…Œ์ด๋„ˆ์— ๋‹ด์•„ ๊ด€๋ฆฌ
    • ์‹ฑ๊ธ€ํ†ค ๋ณด์žฅ: ๊ฐ™์€ ๋นˆ ์š”์ฒญ์ด ์˜ค๋ฉด ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜
    • ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…(DI): ํ•„์š”ํ•œ ๋นˆ์„ ์ฐพ์•„์„œ ๋‹ค๋ฅธ ๋นˆ์— ์ฃผ์ž…
  • ๋นˆ ์กฐํšŒ (Lookup)
    • getBean(String name)
    • getBean(Class<T> requiredType)
      → ์ด๋ฆ„ ๋˜๋Š” ํƒ€์ž…์œผ๋กœ ๋นˆ์„ ๊ฒ€์ƒ‰ํ•ด ๋ฐ˜ํ™˜

 

 

3. IoC(์ œ์–ด์˜ ์—ญ์ „) ์ปจํ…Œ์ด๋„ˆ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ํ•ต์‹ฌ ๋ผˆ๋Œ€

4. ์‹ค๋ฌด์—์„œ๋Š” ์ž˜ ์•ˆ ์”€. ๋ณดํ†ต ApplicationContext๋ฅผ ์“ด๋‹ค, 

 

 

 

 

 

ApplicationContext 

 

 

1. ์šฐ๋ฆฌ๊ฐ€ ์“ฐ๋Š” ApplicationContext๋„ ๊ฒฐ๊ตญ BeanFactory๋ฅผ ์ƒ์†๋ฐ›์•„ ๊ตฌํ˜„๋œ ๊ฒƒ์ด๋‹ค. 

 

2. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ๋•Œ๋Š” ๋นˆ์„ ๊ด€๋ฆฌํ•˜๊ณ  ์กฐํšŒํ•˜๋Š” ๊ธฐ๋Šฅ์€ ๋ฌผ๋ก ์ด๊ณ , ์ˆ˜ ๋งŽ์€ ๋ถ€๊ฐ€๊ธฐ๋Šฅ์ด ํ•„์š”ํ•œ๋ฐ ApplicationContext๊ฐ€ ์ด๋ฅผ ์ œ๊ณตํ•œ๋‹ค. 

 

 

 

 

ApplicatonContext๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ถ€๊ฐ€๊ธฐ๋Šฅ 


 

1. ๋ฉ”์‹œ์ง€ ์†Œ์Šค (MessageSource) → ๊ตญ์ œํ™”(i18n) 

 

  • ์—ฌ๋Ÿฌ ์–ธ์–ด ์ง€์›
  • ๊ฐ™์€ ์ฝ”๋“œ๋ผ๋„ ์‚ฌ์šฉ์ž์˜ Locale(๊ตญ๊ฐ€/์–ธ์–ด ์„ค์ •)์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ

 

String message = context.getMessage("hello", null, Locale.KOREA); 
// "์•ˆ๋…•ํ•˜์„ธ์š”" ์ถœ๋ ฅ

String message = context.getMessage("hello", null, Locale.ENGLISH); 
// "Hello" ์ถœ๋ ฅ

 

 

 

 

 

2. ํ™˜๊ฒฝ ๋ณ€์ˆ˜ (EnvironmentCapable)

 

  • ๋กœ์ปฌ / ๊ฐœ๋ฐœ / ์šด์˜ ํ™˜๊ฒฝ ๊ตฌ๋ถ„
  • ์šด์˜ ํ™˜๊ฒฝ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์„ค์ •๊ฐ’์„ ์ฃผ์ž… ๊ฐ€๋Šฅ

Environment env = context.getEnvironment();
System.out.println(env.getProperty("spring.datasource.url"));

 

-> application-local.properties, application-dev.properties ๊ฐ™์€ ํ”„๋กœํ•„ ๊ธฐ๋ฐ˜ ์„ค์ •๋„ ๊ฐ€๋Šฅ

 

 

 

 

3. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ด๋ฒคํŠธ (ApplicationEventPublisher)

 

  • ์ด๋ฒคํŠธ ๋ฐœํ–‰ / ๊ตฌ๋… ๋ชจ๋ธ ์ง€์›
  • ์˜ต์ €๋ฒ„ ํŒจํ„ด์„ ์Šคํ”„๋ง์ด ์ง์ ‘ ๊ตฌํ˜„ํ•ด์คŒ

 

// ์ด๋ฒคํŠธ ๋ฐœํ–‰
context.publishEvent(new MyCustomEvent(this, "์ด๋ฒคํŠธ ๋ฐœ์ƒ"));

// ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ
@Component
public class MyEventListener {
    @EventListener
    public void handle(MyCustomEvent event) {
        System.out.println("์ด๋ฒคํŠธ ์ˆ˜์‹ : " + event.getMessage());
    }
}

 

 

 

 

4. ๋ฆฌ์†Œ์Šค ๋กœ๋”ฉ (ResourceLoader)

 

  • ๋‹ค์–‘ํ•œ ๋ฆฌ์†Œ์Šค ์ ‘๊ทผ์„ ์ผ๊ด€๋˜๊ฒŒ ์ง€์›
  • ํŒŒ์ผ ์‹œ์Šคํ…œ, ํด๋ž˜์ŠคํŒจ์Šค, ์™ธ๋ถ€ URL ๋“ฑ
Resource resource = context.getResource("classpath:application.properties");
System.out.println(resource.getFilename()); // application.properties

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90