스프링 컨테이너

스프링 컨테이너란?

  • 자바 객체의 생명 주기를 관리하고, 생성된 자바 객체들에게 추가적인 기능을 제공하는 핵심 컴포넌트이다.
  • 스프링 컨테이너에서 자바 객체를 빈(Bean)이라 하고, 빈들의 생성, 관리, 제거 등 생명주기를 관리하고, 빈 간의 관계를 설정한다.
  • 스프링 컨테이너는 @Configuration 애노테이션을 사용하여 자바 구성 클래스로 만들 수 있다.

스프링 컨테이너 생성과정

1. 스프링 컨테이너 생성

  • 구성 클래스를 생성하고, 구성 정보로 지정하면 스프링 컨테이너가 생성된다.

2. 스프링 빈 등록

@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();
    }
}

image

  • 스프링 컨테이너는 파라미터로 넘어온 설정 클래스 정보를 사용해서 스프링 빈을 등록한다.
  • 기본적으로 빈 이름은 메소드 이름을 사용한다. 빈 이름은 중복이 발생하면 기존 빈을 덮어버리는 경우가 발생하기 때문에 주의해야한다.

3. 스프링 빈 의존 관계 설정

image

  • 스프링 컨테이너는 구성 클래스의 설정 정보의 매개변수를 활용하여 의존관계를 주입한다.




싱글톤 컨테이너

스프링은 여러 사용자에게 동시에 서비스하는 웹 애플리케이션을 지원하기 위해서 한개의 인스턴스만을 생성하여 공유하도록 설계하였다. 따라서, 클래스의 인스턴스를 ‘단 1개만’ 생성하기 위해서 싱글톤 패턴을 사용한다.


싱글톤 패턴

public class SingletonService {
   private static final SingletonService instance = new SingletonService();

   public static SingletonService getInstance() {
     return instance;
   }

   private SingletonService() {}

   public void logic() {
     System.out.println("싱글톤 객체 로직 호출");
   }
}
  1. static 영역에 객체 인스턴스를 미리 생성한다.
  2. 객체 인스턴스를 사용하기위해서 getInstance()메서드를 통해서 조회할 수 있는데 이 메서드는 기존에 생성해 놓은 하나의 인스턴스만을 반환한다.
  3. 생성자를 private으로 선언하여 외부로부터 객체 인스턴스 생성을 막는다.

싱글톤 패턴은 DIP, OCP 위반, private 생성자로 자식 클래스 생성, 코드의 길이 등 다양한 문제점이 존재하지만 스프링은 싱글톤 컨테이너를 통해서 문제점을 해결하여 빈을 싱글톤으로 관리한다.


싱글톤 컨테이너

  • 스프링 컨테이너는 싱글톤 컨테이너 역할을 한다.
  • 객체(빈)을 한개만 생성하여 관리하고, 싱글톤 패턴의 문제점을 해결하여 객체를 싱글톤으로 유지할 수 있도록 한다.
    image


  • 스프링 컨테이너는 미리 객체를 생성하고, 사용자에게 미리 생성해둔 객체를 공유하여 반환해 효율적으로 사용할 수 있도록 한다.

주의할 점

  • 객체 인스턴스를 하나만 생성해서 공유하는 방식이기 때문에 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하게 된다. 따라서, 객체의 상태를 유지하도록 설계하지 않고 반드시 무상태(stateless)설계하여야 한다.
  • 클라이언트 코드에는 의존적인 필드와 값이 변경 가능한 코드를 넣어선 안되고, 가급적 읽기만 가능하도록 하여야한다.