Spring IoC, DI 및 스프링 컨테이너(BeanFactory, AppplicationContext)

kmb·2022년 7월 17일
0

스프링

목록 보기
2/9
post-thumbnail

제어의 역전 (IoC, Inversion of Control)

인스턴스의 생성부터 소멸까지의 생명주기관리에 대한 제어권을 개발자가 아닌 IoC 컨테이너 (스프링 컨테이너)가 갖는것.
즉 프로그램의 제어 흐름 구조가 뒤바뀐것.

 

  • 개발자가 직접 객체를 생성하는 방향

상위객체가 하위객체에 의존한다.

  • 프레임워크가 객체를 생성하는 방향

인터페이스를 통해서 하위객체(Impl)가 상위객체에 의존하게 한다. (DIP 충족)
인터페이스의 구현클래스가 확장하더라도 인터페이스에 의존하는 클라이언트 객체는 변화에 닫혀있다. (OCP 충족)


스프링 프레임워크에서 IoC 컨테이너(스프링 컨테이너)에 있는 ApplicationContextBeanFactory 인터페이스를 사용해서 Bean으로 지정한 모든 클래스를 인스턴스로 등록하고, 다른 클래스에서 의존관계가 필요하다면 Bean으로 등록된 인스턴스를 전달하여 의존성주입(DI, Dependency Injection)이 가능하다.

이때 IoC 컨테이너가 Bean을 싱글턴 패턴(Singletion Pattern)으로 제공하므로 동일한 객체이며 인스턴스가 과다하게 생성되어 서버에 부담을 주는것을 막는다.

 
IoC 컨테이너(스프링 컨테이너)
스프링에서 DI를 이용하여 애플리케이션을 구성하는 여러 빈(Bean)들의 생명주기(Lifecycle)와 애플리케이션의 서비스 실행 등을 관리하며 생성된 인스턴스들에게 기능을 제공하는 것.

크게 BeanFactoryApplicationContext 로 나뉜다.

Bean
스프링 컨테이너가 관리하는 객체.

BeanFactory
핵심 IoC 컨테이너.
Bean을 등록, 생성, 조회, 반환 관리를 하는 IoC의 기본기능에 초점을 둔다.
Bean을 인스턴스화 및 조회할 수 있는 getBean( ) 메서드가 정의되어있다.
Lazy-loading 방식을 사용하여 Bean을 사용할때만 Bean을 로딩시킨다.

ApplicationContext
BeanFactory를 확장한 IoC 컨테이너.
BeanFactory 기능과 동일하며 추가적으로 관계설정등의 제어 기능에 초점을 둔다.
Eager-loading 방식을 사용하여 런타임시 모든 Bean을 로딩시킨다.

 
BeanFactory vs ApplicationContext
JPA에서는 Lazy-loading을 권장하지만,
스프링 공식문서에는 두 컨테이너중 Eager-loading인 ApplicationContext의 사용을 권장한다.

왜? Lazy-loading의 경우 해당 Bean을 사용하는 시점이 되기까지 오류를 파악하기 어렵다.
따라서 Eager-loading으로 객체의 초기화 시점에 오류를 잡아낸다.
하지만 통합테스트 관점에서 Eager-loading는 모든 Bean이 한꺼번에 스프링컨테이너에 올라가므로, 이때는 Lazy-loading을 사용한다.

  • 스프링의 Bean 정의 방법
  1. @Configuration + @Bean 어노테이션 사용

  2. @Component 어노테이션 사용

@Component 어노테이션에 해당되는 모든 어노테이션들은 Bean으로 등록된다.
( @Controller, @Service, @Repository는 모두 내부적으로 @Component 어노테이션이 정의되어있다. )

스프링부트에서 처음 실행이 될때 @SpringBootApplication 어노테이션 내부에 @ComponentSacn 어노테이션이 정의되어있다.
@ComponentScan 어노테이션은 @Component 어노테이션이 붙어있는 클래스들을 모두 찾아서 Bean으로 등록하는 역할을 한다.


의존관계 주입 (DI, Dependency Injection)

스프링 컨테이너가 관심사의 분리(생성과 사용의 분리)로 객체의 의존관계를 연결해주는 기술.

 

  • 관심사의 분리(생성과 사용의 분리)

스프링 컨테이너에 있는 ApplcationContext 인터페이스를 이용해서 객체를 생성하고
클라이언트 객체는 생성된 객체를 사용해서 호출만 하면 된다.

 

  • 스프링을 통한 의존성 주입 방법
  1. XML파일에서 속성 주입
  2. @RequiredargsConstructor 어노테이션 + 생성자를 이용한 생성자 주입 방식(Constructor Injection)
  3. 필드@Autowired 어노테이션을 붙이는 필드 주입 방식(Field Injection)
  4. Setter 메서드@Autowired 어노테이션을 붙이는 수정자 주입 방식(Setter Injection)

스프링 4.0부터는 생성자 주입방식을 많이 사용한다.

 

  • DI 장점
  1. 클래스들간의 의존관계를 최소화
  2. 코드를 확장하거나 변경할때 영향을 최소화한다. (추상화)
  3. 의존성으로 부터 격리시켜 코드 테스트에 용이하다

출처

profile
꾸준하게

0개의 댓글