Singleton 의존관계 자동 주입

2 minute read

의존관계 주입 방법

생성자 주입

  • 생성자 호출 시점에 딱 1번만 호출되는 것이 보장된다.
  • 불편, 필수 의존관계에 사용
  • 생성자가 딱 1개만 있다면 @Autowired 생략 가능!

수정자(Setter) 주입

  • setter 메서드를 통해 의존관계 주입
  • 선택 변경 가능성 있는 의존관계에 사용

필드 주입

  • 외부에서 변경이 불가능해서 테스트하기가 굉장히 어려움.
  • DI 프로에임워크가 없으면 아무것 도 할 수 없다.
  • 테스트 코드가 아니라면 사용하지말자!!

일반 메서드 주입

  • 한번에 여러필드 주입을 받을 수 있다.
  • setter 주입과 비슷하기 때문에 일반적으로 잘 사용하지 않는다.

스프링 컨테이너가 관리하는 스프링 빈에서만 의존관계 주입이 동작한다.

생성자 주입을 선택해라!

불변

  • 대부분의 의존관계 주입은 한번 일어나면 어플리케이션 종료시점까지 의존관계를 변경할 일이 없다.
  • 오히려 의존관계는 어플리케이션 종료 전까지 변하면 안된다.
  • 변경하면 안되는 메서드를 열어두는 것은 좋은 설계가 아니다.
  • 생성자 주입은 객체를 생성할 때 딱 1번만 호출되므로 이후에 호출되는 일이 없다.
  • 불변하게 설계할 수 있다.

누락 방지 final keyword

조회 대상 bean 2개 이상일 때 해결 방법

@Autowired 필드명 매칭

  • @Autowired는 타입 매칭을 시도하고, 이때 여러 빈이 있으면 필드 이름, 파라미터 이름으로 빈 이름을 추가 매칭한다.

@Qualifier

  • 추가 구분자를 붙여주는 방법, 주입시 추가적인 방법을 제공하는 것이지 빈 이름을 변경하는 것은 아니다.

@Primary 사용

  • 자주쓰는 빈에 @Primary 적용하고 서브로 사용하는 빈에 @Qualifier 지정하여 명시적으로 구별
  • @Qualifier가 @Primary보다 우선권이 높음!

Spring Bean 라이프 사이클

  • 객체생성 -> 의존관계 주입
  • 스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 -> 사용 -> 소멸전 콜백 -> 스프링 종료
  • 초기화 콜백 : 빈이 생성되고, 빈의 의존관계 주입이 완료된 후 호출
  • 소멸전 콜백 : 빈이 소멸되기 직전에 호출

빈 스코프

스코프란? : 빈이 존재할 수 있는 범위

  • 싱글톤 : 기본 스코프, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프
  • 프로토타입 : 스프링 컨테이너는 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프
  • 웹 관련 스코프
    • request : 웹 요청이 들어오고 나갈때까지 유지되는 스코프
    • session : 웹 세션이 생성되고 종료될 때 까지 유지되는 스코프
    • application : 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프

프로토타입 스코프

싱글톤 스코프의 빈을 조회하면 스프링 컨테이너는 항상 같은 인스턴스의 스프링 빈을 반환한다. 반면에 프로토타입 스코프를 스프링 컨테이너에 조회하면 컨테이너는 항상 새로운 인스턴스를 생성해서 반환한다.

싱글톤 빈 요청


프로토타입 빈 요청



여기서 핵심은 스프링 컨테이너는 프로토타입 빈을 생성하고, 의존관계 주입, 초기화까지만 처리한다는 것이다. 클라이언트에 빈을 반환하고, 이후 스프링 컨테이너는 생성된 프로토타입 빈을 관리하지 않는다. 프로토타입 빈을 관리할 책임은 프로토타입 빈을 받은 클라이언트에 있다. 그래서 @PreDestroy 같은 종료 메서드가 호출되지 않는다.

싱글톤 빈은 스프링 컨테이너 생성 시점에 초기화 메서드가 실행되지만, 프로토타입 스코프 빈은 컨테이너에서 빈을 조회할 때 생성되고, 초기화 메서드도 실행된다. 싱글톤 빈은 스프링 컨테이너가 관리하기 때문에 스프링 컨테이너가 종료될 때 빈의 종료 메서드가 실행되지만, 프로토타입 빈은 스프링 컨테이너가 생성과 의존관계 주입 그리고 초기화 까지만 관여하고, 더는 관리하지 않는다. 따라서 프로토타입 빈은 스프링 컨테이너가 종료될 때 @PreDestroy 같은 종료 메서드가 전혀 실행되지 않는다. 프로토 타입 빈을 조회한 클라이언트가 관리해야한다. 종료 메서드에 대한 호출도 클라이언트가 직접 해야한다.

프로토타입 스코프 - 싱클톤 빈과 함께 사용시 문제점

스프링 컨테이너에 프로토타입 스코프의 빈을 요청하면 항상 새로운 객체 인스턴스를 생성해서 반환한다. 하지만 싱글톤 빈과 함께 사용할 때는 의도한 대로 잘 동작하지 않아 주의가 필요하다.</br></br>

</br> </br></br></br>

</br> </br></br></br>

스프링은 일반적으로 싱글톤 빈을 사용하므로, 싱글톤 빈이 프로토타입 빈을 사용하게 된다. 그런데 싱글톤 빈은 생성 시점에만 의존관계 주입을 받기 때문에, 프로토타입 빈이 새로 생성되기는 하지만, 싱글톤 빈과 함께 계속 유지되는 것이 문제다.

의존관계를 외부에서 주입(DI)받는게 아니라 필요한 의존관계를 찾는 것을 Dependency Lookup(DL) 의존관계 조회(탐색) 이라고 한다. DL 기능만 제공하는 무언가 있으면 해결 가능함.

ObjectFactory, ObjectProvider

ObjectProvider의 getObject() 를 호출하면 내부에서는 스프링 컨테이너를 통해 해당 빈을 찾아서 반환한다. (DL)

웹스코프

  • 웹 스코프는 웹 환경에서만 동작
  • 웹 스코프는 프로토타입과 다르게 스프링이 해당 스코프의 종료시점까지 관리한다. 따라서 종료 메서드가 호출된다.

Categories:

Updated: