5.빈의 스코프

앞에까지는 아무 설정도 하지 않은 싱글톤 스코프의 빈을 사용하였다.
(강사님은 싱글톤 스코프 외에는 사용할 일이 거의 없을거라 하심.)

싱글톤 스코프

싱글톤 스코프 : 어플리케이션에 걸쳐 인스턴스가 하나뿐!
어플리케이션 콘텍스트를 만들 때 만들어진다. 즉 어플리케이션 구동 시 시간이 길어질 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Component
public class Proto {
@Autowired
Single single;
}


@Component
public class Single {
@Autowired
Proto proto;

public Proto getProto() {
return proto;
}
}

프로토타입 스코프

프로토타입 스코프 : 매번 새로운 인스턴스를 만드는 스코프
@Scope(“prototype”) 를 붙여주면 된다.

1
2
3
4
5
6
@Component @Scope("prototype")
public class Proto {
@Autowired
Single single;
}

위 처럼 프로토 타입 빈이 싱글톤 빈을 참조하면 문제가 없다
(프로토타입의 빈은 매번 새롭겠지만 프로토타입의 빈은 동일 한 것)

하지만 싱글톤 빈이 프로토 타입 빈을 참조하면??

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Component
public class Single {

@Autowired
private Proto proto;

public Proto getProto() {
return proto;
}
}



....getBean(Single.class).getProto()
....getBean(Single.class).getProto()
....getBean(Single.class).getProto()


마지막 3줄의 Proto 는 모두 동일
의도한 바가 아님!

해결방법은?

해결방법 1. scoped-proxy

1
2
3
4
@Component @Scope("prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Proto {

}

Proto 빈을 클래스기반 프록시로 감싸라
프록시로 감싸는 이유 : 다른 빈들이 프로토 빈을 직접 참조하면 안되기 때문에… 직접 쓰면 바궈줄 여지가 없다. cg라이브러리를 활용해 클래스 기반 프록시를 만들어준다.

Single 내 Proto의 참조변수는 Proto 클래스를 상속한 Proxy가 주입되게 되는것이다.

해결방법 2.ObjectProvider

1번이 어렵고 성능에도 영향을 줄것같다면 이 방법을 쓰자. 하지만 ObjectProvider라는 스프링 코드가 들어가기 때문에 조금 그렇다….

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Component @Scope("prototype")
public class Proto {
}

@Component
public class Single {

@Autowired
private ObjectProvider<Proto> proto;

public Proto getProto() {
return proto.getIfAvailable();
}
}

싱글톤 객체를 사용할 때 주의해야 할 점

1
2
3
4
5
6
7
8
9
@Component
public class Single {

int counter;

...

counter++; //Thread Safe하지 않다.
}

참고할것

https://en.wikipedia.org/wiki/Proxy_pattern

Share