
스프링 핵심원리 - 기본편 강의를 정리하는 마지막 글이다. 이번에는 빈의 생명주기와, 빈 스코프에 대해서 알아볼 것이다.
스프링 빈의 라이프 사이클은 다음과 같다. (싱글톤 기준)
1. 스프링 컨테이너 생성생성과 초기화를 분리하자
- 생성은 객체의 필수적인 값만 받아 메모리를 할당하는 것이고, 초기화는 할당된 값들을 활용하여 외부 커넥션을 연결하는 등 무거운 작업을 수행한다. (초기화 작업이 가벼운 경우, 생성과 동시에 처리 가능)
여기서 4,6번의 콜백함수를 지정하는 방법은 총 3가지가 있다. 3가지 방법에 대해서 알아보자
세가지 방법
- 등록할 빈이 InitializingBean과 DisposableBean 인터페이스를 구현한다.

등록할 빈에 위 인터페이스를 구현한다고 선언하고

위의 소멸 콜백 로직을 작성할 destroy 메서드, 초기화 콜백 로직을 작성할 afterPropertiesSet 메서드를 오버라이딩 해주면 된다.
- @Bean 어노테이션으로 등록을 함과 동시에 옵션으로 initMethod, destroyMethod에 콜백함수명을 지정한다.

위와 같이 등록을 함과 동시에 콜백메서드 명을 지정한다.

만들어 놓은 콜백 메서드이다.
+ destroyMethod 속성은 디폴트 값(inferred)으로 되어있으면 'close', 'shotdown' 이름의 메서드를 찾아(추론) 자동호출한다.
- @PostConstruct, @PreDestroy 어노테이션을 붙혀 콜백 메서드로 지정한다.

위처럼 메서드에 어노테이션만 붙혀 콜백으로 등록한다.
- 말 그대로, 빈이 존재할 수 있는 범위
빈 스코프는 총 6종류가 있다.

1. 싱글톤 - 앞에서 설명했듯이 1개의 객체의 생성을 보장해주고, 스프링 컨테이너의 시작과 종료까지 존재한다.
2. 프로토타입 - 조회 시 등록된 빈의 새로운 인스턴스를 반환해주고, 스프링이 생성, 의존관계 주입, 초기화 까지만 관여한다. 이후에는 클라이언트가 관리해야한다.
3 ~. 나머지는 웹과 관련된 스코프다. 대표적으로 request 스코프는 각각의 http 요청이 들어오고 나갈 때마다 생성되고 소멸된다.
싱글톤과 프로토타입 스코프를 동시에 사용하면 문제가 될 경우가 있다. 싱글톤으로 등록된 빈이 필드로 프로토타입 스코프로 등록된 빈을 가지는데, 등록된 프로토타입 스코프의 빈이 새로운 객체처럼 동작하는 것을 기대할 경우이다.
말이 어려우니 그림을 통해서 보겠다.

위와 같이 스프링 컨테이너에 싱글톤으로 등록된 빈은 의존관계 주입 때 새로운 프로토타입 객체에 의존하게 된다.

그리고 A클라이언트는 ClientBean을 받아 logic을 호출하여 프로토타입 객체의 필드의 Count가 0에서 1로 올라가게 된다.

그런데 여기서 B클라이언트가 또다시 ClientBean을 받아 addCount를 하는 logic을 호출한다.
이 때 PrototypeBean을 프로토타입 스코프로 지정했기 때문에 새로운 객체를 생성하여 카운팅 한다고 생각할 수 도 있지만,
이미 싱글톤에 의존관계를 주입할 때 생성된 객체에 다시 카운팅을 하게된다.
그렇다면 클라이언트가 logic을 호출할 때마다 프로토타입으로 등록된 새로운 객체를 가져오려면 어떻게 해야할까?
가장 먼저 떠오르는 방법은 각각의 logic마다 스프링 컨테이너에 프로토타입을 빈을 달라고 요청하는 것이다.(DL)
하지만 이렇게 되면 스프링 컨테이너를 직접 멤버로 가지고 있어야하는데 이렇게 되면 단위 테스트도 힘들어지고 무거운 느낌이 든다.
이것을 해결해줄 수 있는 것이 Provider이다.
- 외부에서 의존관계를 주입 받는 것은DI, 직접 의존관계를 찾는 것은 DL(Dependency Lookup)이라고 한다.
Provider를 이용하면 스프링 컨테이너를 멤버로 가질 필요 없이 직접 컨테이너에 빈을 찾도록 요청할 수 있다
스프링에서는 ObjectProvider과 ObjectFactory 클래스를 통해 얻을 수 있고, 자바표준으로도 Provider 클래스를 통해 얻을 수 있다.
👆자바표준 Provider 사용법

👆스프링 ObjectProvider/ObjectFactory 사용법
둘 모두 사용법은 비슷하다. 제네릭으로 조회할 타입을 지정하고 get~ 메서드를 이용하여 컨테이너에 직접 요청하는 것이다!
☝ObecjtProvider, ObjectFactory 차이점

ObjectProvider는 ObjectFactory를 상속한 기존 DL기능에 편의 기능을 더한 것이다.
웹 스코프는 예제 중심이기 간략하게 정리만 하자면(절대 귀찮아서 그러는거 아님..)
웹 스코프는 http요청, session 등 웹과 관련된 것에 생명주기를 두고있다.
앞에서 싱글톤과 프로토타입 같이 사용할 때의 문제를 Provider를 사용하여 한 것처럼, http request를 기록할 Logger를 만들 때 싱글톤과 request 스코프 같이 사용하는데 Provider를 이용할 수 있다.
그런데 여기서 Provider가 아닌 그냥 미리 싱글톤처럼 등록하고 역할을 위임하는 프록시를 활용해서도 해결할 수 있다.
스프링 핵심원리 기본편 정리가 끝났다. 지난학기 때 아무것도 모를 때 맨땅에 박치기 하는 느낌으로 스프링으로 프로젝트를 했었는데, 지금 다시 돌아가보면 어떤식으로 돌아가는지 이해할 수 있을 것 같다.
그때 했던 프로젝트를 리팩토링하고, 미완성이었던 부분을 보충해서 끝까지 한번 만들어봐야겠다👊👊
자료 출처: 영한님 스프링 기본편 강의 , 스프링 공식 문서