본문 바로가기
개발/Spring

[스프링] 스프링 핵심원리 - 스프링 컨테이너와 빈

by 윤호 2021. 12. 5.

Ioc, DI, 컨테이너, 빈

IoC (Inversion of Control)

  • 프로그램의 제어 흐름을 직접 제어하는 거이 아니라 외부에서 관리하는 것을 제어의 역전(IoC)라 한다.
  • 프레임워크는 내가 작성한 코드를 제어하고, 대신 실행한다.

DI (Dependency Injection)

  • 한 객체가 추상화에만 의존할 수 있도록 어떤 구현체에 의존할 지는 AppConfig 같은 외부 클래스에서 결정하고 의존관계를 주입함
  • 의존 관계는 정적인 클래스 의존 관계와, 실행 시점에 결정되는 동적인 객체(인스턴스) 의존 관계를 구분해서 생각해야함
  • 외부에서 실제 구현 객체를 생성하고 클라이언트에 전달해서 실제 의존관계가 연결 되는 것을 의존관계 주입이라 한다.
  • 의존관계 주입을 사용하면 정적 의존 관계를 변경하지 않고, 동적 의존 관계를 변경할 수 있다.

IoC 컨테이너, DI 컨테이너

  • 의존관계 주입을 대신 해주는 것을 DI 컨테이너(혹은 Ioc 컨테이너)라고함
  • 스프링을 사용하면 DI 컨테이너 = Ioc 컨테이너 = 스프링 컨테이너

스프링 빈

  • 스프링 컨테이너에서 관리하는 객체를 스프링 빈(Bean)이라고 한다.
  • 빈 이름은 항상 다른 이름을 부여해야 한다.

스프링 빈 등록 및 컨테이너 생성

@Bean을 이용해 빈을 등록할 수 있다. 

@Configuration
public class AppConfig {

    // 빈 이름은 기본적으로 메소드 이름으로 등록됨
    @Bean
    public MemberService memberService(){
        // 생성자를 통해 구현 객체 주입 - 생성자 주입
        return new MemberServiceImpl(memberRepository());
    }
}

ApplicationContext가 컨테이너가 된다.

ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

AnnotationConfigApplicationContext 은 ApplicationContext의 구현체로, 자바 파일로 컨테이너를 생성한다. (xml을 이용하는 구현체도 있음)

 

빈 조회

빈 이름과 타입으로 조회할 수 있다.

    // ("빈 이름으로 조회")
    MemberService memberService = ac.getBean("memberService", MemberService.class);

    // ("이름 없이 타입으로만 조회")
    MemberService memberService = ac.getBean(MemberService.class);

    // ("구체 타입으로 조회")
    MemberService memberService = ac.getBean("memberService", MemberServiceImpl.class);

타입으로 조회했을 때, 두 개 이상의 빈이 나와 오류가 날 수 있다.

자식타입이 있을 경우, 자식 타입의 빈도 모두 나옴.

그럴때는 이름을 지정하여 조회하자.

 

특정 타입의 빈을 모두 조회하는 코드

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);

 

컨테이너의 모든 빈을 조회하는 코드

String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
	Object bean = ac.getBean(beanDefinitionName);
	System.out.println("name = " + beanDefinitionName + " object = " + bean);
}

 

애플리케이션 빈을 모두 조회하는 코드

String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
        Object bean = ac.getBean(beanDefinitionName);
        System.out.println("name = " + beanDefinitionName + " object = " + bean);
}

reference : 인프런 김영한 강사님 스프링핵심원리

댓글