728x90
반응형
싱글톤과 프로토타입을 같이 사용했을때 문제점 해결
앞에서 싱글톤과 프로토타입을 같이 사용하면 발생되는 문제점을 봤다.
https://vprog1215.tistory.com/79
Provider 로 해결하는 방법을 알아보자
Spring 의 Provider 기능 사용.
스프링에서 제공해 주는 Provider기능을 사용하면 다음과 같이 간결하게 구현 할 수 있다.
특징
ObjectProvider 사용
- ObjectProvider 를 선언을 먼저 해준다.
- 그렇게 되면 컨테이너에서 해당 빈을 찾을수가 있다.
- ObjectFactory 를 상속받아 ObjectProvider 가 구현되어 있다.
- ApplicationContext ac; 를 사용하지 않고도 쉽게 Bean을 가져올수 있다.
- getObject() 를 호출하여 스프링컨테이너를 통해 해당빈을 찾아서 반환한다. (DL 이라고한다.)
코드 설명
// ClientBean 은 싱글톤
@Scope("singleton")
static class ClientBean {
/*
// 생성시점에 주입 그래서 계속 같은걸 쓴다.
// 처음 주입때만 생성한다.
// private final PrototypeBean prototypeBean;
@Autowired
ApplicationContext ac;
// 이때 PrototypeBean을 요청하고 찾는다.
// 이미 생성시점에 만들어 진 애를 사용한다.
@Autowired
public ClientBean(PrototypeBean prototypeBean) {
this.prototypeBean = prototypeBean;
}
public int logic() {
// 여기가 핵심이다. 그냥 부를때 마다 빈을 가져온다.
// 그렇게 되면 프로토타입의 동작을 제대로 한다.
PrototypeBean prototypeBean = ac.getBean(PrototypeBean.class);
prototypeBean.addCount();
return prototypeBean.getCount();
}
*/
@Autowired
//private ObjectProvider<PrototypeBean> prototypeBeanProvider; //방법1
private ObjectFactory<PrototypeBean> prototypeBeanProvider; //방법2
public int logic() {
// 항상 새로운 타입의 프로토타입이 생성됨.
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
}
JSR-330 Provider 사용
사용법
- gradle 에 'java.inject:javax.inject:1'
- private ObjectFactory<PrototypeBean> prototypeBeanProvider; 에서
private Provider<PrototypeBean> prototypeBeanProvider; 변경 - getObject() 에서 get() 으로 변경만 해주면된다.
특징
- 자바표준이다. 스프링말고도 다른곳에서 사용가능하다.
- 별도의 라이브러리 추가 필요
- get() 하나만으로 해결
build.gradle 파일
plugins {
id 'org.springframework.boot' version '2.4.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'hello'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
//lombok 설정 추가 시작
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
//lombok 설정 추가 끝
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
// JSR-330 Provider
implementation 'java.inject:javax.inject:1'
//lombok 라이브러리 추가 시작
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
//lombok 라이브러리 추가 시작
testImplementation ('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit'
}
}
test {
useJUnitPlatform()
}
코드구현
// ClientBean 은 싱글톤
@Scope("singleton")
static class ClientBean {
/*
// 생성시점에 주입 그래서 계속 같은걸 쓴다.
// 처음 주입때만 생성한다.
// private final PrototypeBean prototypeBean;
@Autowired
ApplicationContext ac;
// 이때 PrototypeBean을 요청하고 찾는다.
// 이미 생성시점에 만들어 진 애를 사용한다.
@Autowired
public ClientBean(PrototypeBean prototypeBean) {
this.prototypeBean = prototypeBean;
}
public int logic() {
// 여기가 핵심이다. 그냥 부를때 마다 빈을 가져온다.
// 그렇게 되면 프로토타입의 동작을 제대로 한다.
PrototypeBean prototypeBean = ac.getBean(PrototypeBean.class);
prototypeBean.addCount();
return prototypeBean.getCount();
}
*/
/*
@Autowired
//private ObjectProvider<PrototypeBean> prototypeBeanProvider; //방법1
private ObjectFactory<PrototypeBean> prototypeBeanProvider; //방법2
public int logic() {
// 항상 새로운 타입의 프로토타입이 생성됨.
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
*/
@Autowired
private Provider<PrototypeBean> prototypeBeanProvider;
public int logic() {
// 항상 새로운 타입의 프로토타입이 생성됨.
PrototypeBean prototypeBean = prototypeBeanProvider.get();
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
}
정리
- Prototype은 잘 사용되지 않는다.
- ObjectProvider 는 프로토 타입외에도 DL을 해줄때 사용된다. 편의기능도 있기 때문에 좋다.
- JSR-330 Provider 는 스프링을 사용하지 않을때 쓴다. 정말 잘 쓰지 않아도 된다는것 같다.
728x90
반응형
'Spring > spring 기초 스터디' 카테고리의 다른 글
[Spring] Annotation (0) | 2021.07.23 |
---|---|
[Spring] Bean Scope Web: part4 (0) | 2021.06.15 |
[Spring] Bean Scope Prototype: part2 (0) | 2021.06.12 |
[Spring] Bean Scope Prototype: part1 (0) | 2021.06.01 |
[Spring] Bean Scope (0) | 2021.06.01 |
댓글