티스토리 뷰

빈 생명주기 콜백이란

DB Connection pool - 애플리케이션 서버와 DB 서버를 연결하여 미리 connection을 생성해 두는 것

(자세한 것 아님, 간단한 요약)

 

DB connection pool이나 네트워크 소켓같이 애플리케이션 종료 시점에 연결을 모두 종료하려는

작업을 할 때, 객체의 초기화와 종료작업이 필요함

 

스프링 빈은 객체 생성 후 의존관계 주입이라는 사이클을 갖는다( 생성자 주입은 예외 )

즉, 의존관계 주입이 끝나야 데이터를 사용할 수 있는 준비가 완료되는 것이다.

의존관계 주입이 완료된 시점을 알 수 있는 방법이 바로 콜백이다.

 

스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 -> 사용

-> 소멸 전 콜백 -> 스프링 종료( <- 싱글톤인 이벤트 라이프사이클 )

 

스프링이 지원하는 빈 생명주기 콜백

1. 인터페이스(InitializingBean - 초기화 , DisposableBean - 종료)

인터페이스를 활용하여 초기화, 종료를 사용하는 방법

-> 이는 스프링 전용 인터페이스, 그렇기에 의존적이고 메서드 이름을 변경할 수 없는 단점이 있다.

 

2. 빈 등록 초기화, 소멸 메서드

빈 등록 시 initMethod와 destroyMethod에 메서드 이름을 할당하는 방법

-> 메서드 이름을 변경할 수 있고, 설정 정보를 사용하기에 외부 라이브러리에서도 적용 가능

-> @Bean의 destroyMethod는 기본 값이 infeerred 추론이다.

      그래서 값을 지정하지 않아도 close, shutdown(이 둘이 종료 관례) 이름의 메서드를 자동으로 호출해준다.

 

3. 애노테이션 @PostConstruct, @PreDestroy

메서드에 애노테이션만 붙이는 방법

-> 패키지가 javax.annotation. 이다. 자바 표준이기에 다른 컨테이너에서도 잘 동작한다.

     유일한 단점은 외부 라이브러리에 적용을 하지 못한다는 점 - 이 부분은 2번 @Bean을 사용하자

 

 

빈 스코프

스프링 빈이 스프링 컨테이너의 시작과 함께 생성되어 종료때까지 유지된다

-> 이는 스프링 빈이 기본적으로 싱글톤 스코프로 생성되기 때문

빈 스코프는 빈이 존재하는 범위를 뜻한다.

스프링이 지원하는 스코프 종류

 1. 싱글톤 - 기본, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위 *

 2. 프로토타입 - 빈의 생성과 의존관계 주입까지만 관여하는 짧은 범위 *

 3. 웹 관련 스코프

    request - 웹 요청이 들어오고 나갈때까지 유지되는 스코프 *

    session - 웹 세션이 생성되고 종료때까지 유지되는 스코프

    application - 웹의 서블릿 컨텍스와 같은 범위로 유지되는 스코프 

 

 

프로토타입 스코프 

싱글톤 스코프는 빈을 조회하면 항상 같은 인스턴스를 반환한다.

반면, 프로토타입 스코프는 항상 새로운 인스턴스를 반환한다.

프로토타입 스코프의 요청과 반환 과정

클라이언트가 요청을 할 시점에 새로운 빈을 생성하여 의존관계를 주입하고, 클라이언트에 반환한다.

이후 관리하지 않고, 관리를 하더라도 클라이언트의 책임이 있는 설정이다.

 

 

 

프로토타입 스코프와 싱글톤 빈을 함께 사용하면 발생하는 문제점

프로토타입 빈을 사용하려는 경우 - 각각의 인스턴스를 생성하여 확인하는 ( 각 사용자의 방문 수 등.. )

싱글톤 빈은 생성 시점에만 의존관계를 주입받는다.

그렇기에 이때 생성되는 프로토타입 빈은 싱글톤 빈과 함께 주입 받고 계속 유지되는 것

-> 문제가 되는 이유? A이용자의 방문 수와 B이용자의 방문 수가 공유되어 증가되는 문제가 있을 수도

 

clientBean(싱글톤 빈)생성 시점에 함께 생성된 prototypeBean, 그렇기에 prototypeBean의 logic이 공유된다.

 

어떻게 사용할 때마다 프로토타입 빈을 생성할 수 있을까?

@Autowired
private ApplicationContext ac;

public int logic() {
	PrototypeBean prototypeBean = ac.getBean(PrototypeBean.class);
 	prototypeBean.addCount();
 	int count = prototypeBean.getCount();
 	return count;
}

위 코드를 보면 logic이 실행될 때 프로토타입 빈을 생성하여 이전 로직을 수행한다. 

이렇게 한다면 logic 실행 마다 생성되기 때문에 서로 다른 프로토타입 빈을 사용할 수 있다.

이런 방식처럼 의존관계를 외부에서 주입받는 것이 아닌 직접 의존관계를 찾는 것을 DL(Dependency Lookup, 의존관계) 이라 한다.

위 코드는 로직마다 ApplicationContext를 주입받으면 스프링 컨테이너에 종속적이게 된다.

 

DL 기능만 제공하는 ObjectProvider와 JSR-330 Provider

1. ObjectProvider (ObjectFactory)

@Autowired
private ObjectProvider<PrototypeBean> prototypeBeanProvider;

public int logic() {
	PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
	prototypeBean.addCount();
	int count = prototypeBean.getCount();
	return count;
}

이전 코드와 비슷한 맥락이다. 단 ObjectProvider의 getObject메서드는 스프링 컨테니어를 통해 해당 빈을 찾아 제공한다.

 

2. JSR-330 Provider

@Autowired
private Provider<PrototypeBean> provider;

public int logic() {
	PrototypeBean prototypeBean = provider.get();
	prototypeBean.addCount();
	int count = prototypeBean.getCount();
	return count;
}

이는 자바 표준 javax.inject.Provider를 사용한다. - ( 부트 3.0미만 가능, 이상은 jakarta.inject.Provider )

ObjectProvider와 마찬가지로 동작하며, 이는 라이브러리를 추가해야 하지만 자바 표준이기 때문에 다른 컨테이너에도 적용 가능하다.

 

 

웹 스코프

웹 스코프는 웹 환경에서만 동작하고, 스프링이 해당 스코프의 종료시점까지 관리한다. 

1. request - HTTP 요청 하나가 들어오고 나갈 때 까지 유지되는 스코프, 각 요청마다 별도의 빈 인스턴스 생성 및 관리

요청에 따른 서로 다른 빈 인스턴스 생성

2. session: HTTP Session과 동일한 생명주기를 가지는 스코프

3. application: 서블릿 컨텍스트( ServletContext )와 동일한 생명주기를 가지는 스코프

4. websocket: 웹 소켓과 동일한 생명주기를 가지는 스코프

 

 

스코프와 프록시

프록시 -  "대리"의 의미로, 내부 네트워크에서 인터넷 접속을 할 때에, 빠른 액세스나 안전한 통신등을 확보하기 위한

                중계서버를  "프록시 서버"라고 일컫는다. 클라이언트와 Web서버의 중간에 위치하고 있어,   

                대신 통신을 받아 주는 것이 프록시 서버이다. -> 대신, 가짜로 

ObjectProvider 대신 proxy를 사용함

CGLIB 라이브러리로 가짜 프록시 객체를 만들고, 이 객체가 MyLogger대신(프록시하다) 등록된다.

의존관계 주입 또한 가짜 프록시 객체가 주입된다.

이 객체는 요청이 오면 그때 내부에서 진짜 빈을 요청하는 위임 로직이 존재

-> 미리 만들어두고 요청이 오면 찾기 때문에 ObjectProvider 처럼 사용할 수 있다.

 

 

 

 

 

 

 

본 포스팅은 인프런 강의 김영한님의

[ 스프링 핵심 원리 - 기본편 ] 을 수강하며 작성한 내용입니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30