스코프(Scope) - 1. 빈 스코프

HYUNBIN CHO·2021년 4월 17일
0

spring

목록 보기
13/23
post-thumbnail

🔷 스프링이 지원하는 다양한 스코프

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

🔷 빈 스코프란

빈 스코프(Bean Scope) : 스프링 빈이 존재할 수 있는 범위
기본적으로 스프링 빈이 싱글톤 스코프로 생성되기 때문에 스프링 컨테이너의 시작과 함께 생성되어 스프링 컨테이너가 종료될 때까지 유지된다.

🔷 빈 스코프 지정 방법

🔸 컴포넌트 자동등록

@Scope("prototype")
@Component
public class HelloBean{}

🔸직접 등록

@Scope("prototype")
@Bean
PrototypeBean HelloBean(){
	return new HelloBean();
}

🔷 싱글톤 스코프

🔸 싱글톤 빈은 스프링 컨테이너의 생성시점에 빈 생성 및 초기화 메서드가 실행된다.

🔷 프로토타입 스코프

🔸프로토타입 스코프의 스프링 빈은 스프링 컨테이너에서 빈을 조회할 때 생성, 초기화 메서드가 실행된다.
🔸프로토타입 스코프의 경우에는 클라이언트가 요청한 빈을 반환한 후 관리하지 않는다 ➡️ 종료메서드(@PreDestroy)를 호출하지 않는다.
➡️ 종료메서드를 호출할 필요가 있을 경우, 스프링 컨테이너가 아닌 클라이언트가 호출해야 한다.

🔷 싱글톤 스코프과 프로토타입 빈을 함께 사용할 때의 문제점

🔸 프로토타입 빈이 목적은 호출할 때마다 새로운 빈을 생성하기 위함인데, 싱글톤 빈의 생성자로 의존관계 주입을 받게된다면?
🔸 예

public class ClientBean{
   private final PrototypeBean prototypeBean;

   @Autowired
   public ClientBean(PrototypeBean prototypeBean){
   	this.prototypeBean = prototypeBean;
   }
   public int logic(){
       prototypeBean.addCount();
       int count = prototypeBean.getCount();
       return count;
   }
}

public class SigletonUsePrototype{
   AnnotationConfigApplicationContext ac =
       new AnnotationConfigApplicationContext(ClientBean.class,
               PrototypeBean.class);

   ClientBean clientBean1 = ac.getBean(ClientBean.class);
   ClientBean clientBean2 = ac.getBean(ClientBean.class);
   int count1 = clientBean1.logic();
   int count2 = clientBean2.logic();
}

count1 = 1, count2 = 1이 우리의 기대값이지만 실제 결과는 count1 = 1, count2 = 2;
➡️ 처음 생성할 때 한 번 의존관계 주입을 받고 이후에는 계속해서 같은 참조값을 가진 프로토타입 빈을 사용하게 된다.

🔷 해결방법 - Provider

🔹 ObjectProvider, ObjectFactory

public class ClinetBean{
   @Autowired
   private ObjectProvider<PrototypeBean> prototypeBeanProvider;

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

🔸ObjectProvider.getObject() : 스프링 컨테이너를 통해 해당 빈을 찾아서 반환한다. ➡️ 항상 새로운 프로토 타입 빈을 생성할 수 있다.
🔸 별동의 라이브러리는 필요없지만, 스프링에 의존적이라는 단점.

🔹JSR-330 Provider

🔸 javax.inject.Provider 라는 자바표준을 이용
➡️ build.gradle에 'javax.inject:javax.inject:1'을 추가해야 사용가능

import javax.inject.Provider;

public class ClinetBean{
   @Autowired
   private Provider<PrototypeBean> prototypeBeanProvider;

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

🔸Provider.get() : 스프링 컨테이너를 통해 해당 빈을 찾아서 반환한다. ➡️ 항상 새로운 프로토 타입 빈을 생성할 수 있다.
🔸 별도의 라이브러리가 필요하다는 단점
🔸 자바 표준이기 때문에 스프링이 아닌 다른 컨테이너에서도 사용이 가능하다.

🔸의존관계 조회(Dependency Lookup) : 의존관계를 외부에서 주입받는 것이 아니라 직접 필요한 의존관계를 찾는 것

🔷 프로토타입 빈은 언제 사용할까?

매번 사용할 때마다 의존관계 주입이 완료된 새로운 객체가 필요할 때 사용
‼️하지만 실무에서는 싱글톤 빈으로 대부분의 문제가 해결가능
➡️ObjectProvider, JSR-330 Provider는 프로토타입에만 사용하는 기능이 아니라 DL이 필요한 경우 언제든 사용가능하다.







https://www.inflearn.com/course/스프링-핵심-원리-기본편#

profile
백견이 불여일타

0개의 댓글