💡 Spring 핵심 개념 인터뷰 Q&A
핵심개념
- 스프링 빈 : 스프링 컨테이너에서 관리하는 자바 객체
- 스코프 : 스프링빈이 존재할 수 있는 범위
이 스프링빈도 싱글톤이냐, 프로토타입이냐에 따라 다르다.
스코프
- request : 웹 요청이 들어오고 나갈때까지의 스코프로, 각 요청마다 빈 인스턴스가 생성되고 관뢰된다.
- session: 웹 세션이 생성되고 종료될 떄까지 유지되는 스코프, Http Session과 동일한 생명주기를 가진다.
- application : 웹의 서블릿 컨텍스트와 같은 범위를 유지되는 스코프
- webSocket : 웹 소켓과 동일한 생명주기를 갖는다.
빈 스코드 사용방법
- 일반적으로 스프링이 컴포넌트를 자동스캔하여 등록한다.
- 아래는 프로토 타입의 스코프
@Scope("protype")
@Component
public class protoTypeBean()
싱글톤 빈 스코프경우
- 싱글톤 빈 스코프에서는 스프링 컨테이너는 항상 같은 빈을 반환한다.
- 싱글톤 스코프 빈을 요청하면 동일한 스프링빈을 반환한다.
프로토타입 스코프의 스프링 빈
작동 순서
- 클라이언트에서 프로토타입 스코프의 스프링빈을 스프링 컨테이너에 요청
- 스프링 컨테이너는 이 시점에서 프로토타입 빈을 생성하고, Di
- 생성한 프로토타입 빈을 클라이언트에 반환
- 프로토타입 빈은 빈 생성, 의존관계 주입, 초기화까지만 진행한다.
- 스프링 빈을 클라이언트에 반환한 후 관리하지 않기 때문에 모두 클리이언트에서 관리해야한다.
주소값
싱글콘 스코프
- 싱글통스포프의 스프링 빈은 여러번 호출해도 모두 동일한 인스턴스 주소값을 가진다.
- 스프링 컨테이너 종료할 때 소멸 메서드도 자동으로 실행된다
프로토타입 스코드
- 프로토타입 빈 2개가 참조하는 인스턴스 참조 주소값이 다르다.
- 스프링 컨테이너 종료시 소멸 메서드가 실행되지 않는다.
정리
- 싱글톤은 스프링 컨테이너와 생명주기를 같이하지만, 프로토타입 스프링빈은 생명주기를 달리한다.
- 싱글톤 스프링 빈은 매번 스프링 컨테이너에서 동일한 인스턴스를 반환하지만, 프로토타입빈은 소명 메서드가 호출되지 않는다.
- 클라이언트가 프로토타입 스프링빈을 직접 관리해야한다.
문제상황 : 프로토타입 스코프가 싱글톤 빈과 함께 사용될떄
케이스 : 싱글톤 스프링 빈 내부에 의존관계로 주입되는 스프링 빈이 프로토타입일떄
설명 :
- 싱글톤 빈의 스코프는 스프링 컨테이너와 같은데, 프로토 타입 스코프의 스프링빈이 새로 생성되기는 하지만 싱글톤 빈과 함께 사용되기 때문에 계속 유지된다
- 해당 빈을 2번 요청하지만 동일한 프토토타입 빈을 사용하게 되어 count는 2
- 프로토타입 빈만 클라이언트가 직접 사용하는 경우라면 상관없지만 싱글톤 빈과 함께 사용하면서 프로토타입 빈이 자기의 스코프를 지키고 매번 새롭게 생성하려면?
해결 : 프로토타입 스코프를 싱글톤 빈과 함께 사용할때
- 싱글톤 빈 내부에서 주입된 빈이 프로토타입이면 계속 동일한 인스턴스를 참조하게 되어 프로토타입 스코프를 갖지 못하게 되었다.
- 싱글톤 빈과 프로토타입을 혼용하면서 프로토타입을 매번 생성하려면?
- 의존관계를 외부에서 주입받지 않고 직접 의존관계를 찾는것을 해야한다.
- 이것은 DL(dependency lookup) 의존관계 조회를 말한다.
- .getBean()으로 직접조회해서 주입
이 해결방식의 문제점
- 스프링 애플리케이션 컨텍스트 전체를 주입받게된면 스프링 컨테이너와 종속성이 생기고 테스트가 어렵다.
static class ClientBean{
@Autowired
private ApplicationContext ac;
public int logic() {
PrototypeBean prototypeBean = ac.getBean(PrototypeBean.class);
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
}
해결방식 : ObjectrFactory, ObjectProvider
- ObjectrFactory: 지정한 빈을 컨테이너에서 대신 찾아준다.
- ObjectProvider : ObjectrFactory에 편의기능을 추가해서 만들어진 객체
static class ClientBean{
@Autowired
private ObjectProvider<PrototypeBean> prototypeBeanProvider;
public int logic() {
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
}
- ObjectProvider 을 사용하였고, 매번 새로운 프로토타입 빈이 생성되는 것을 확인할 수 있다.
- ObjectProvider의 getObject()를 호출하면 내부에서는 스프링 컨테이너를 통해 해당 빈을 찾아서 반환(DL)
프로토타입빈 사용목적
- 스프링은 기본세팅이 싱글톤이므로 DL을 해야한다.
- DL해야하는 경우
- 여러 인스턴스검색
- 인스턴스 지연
- 순환 종속성 깨야할때
- 스코프에 포함된 인스턴스로부터 더 작은 범위의 인스턴스를 찾아 추상화하기 위해서 사용한다.
스코프와 Provider, 스코프와 프록시의 동작 원리
- @Scope 의 proxyMode를 사용하면 스프링 컨테이너는 CGLIB이라는 바이트코드 조작 라이브러리를 사용해 가짜 프록시 객체를 생성
- 스프링컨테이너에는 이프록시 객체가 들록된다.
- getbean()을 통해 해당 클래스 타입을 조회해도 가짜 프록시 객체가 조회되는 것을 볼 수 있다.
- CGLIB 이라는 바이트코드 조작 라이브러리로 클래스를 상속받은 가짜 프록시 객체를 만들어 의존관계를 주입하며
- lazyLoading
- 애노테이션 추가속성으로 원본객체레 프록시 객체로 대체가 가능하다.