@Scope를 통해 빈의 스코프를 지정해줄 수 있다.

(디폴트는 싱글톤 빈이다.)

 

프로토타입.

@Scope("prototype") 으로 지정해준다.

싱글톤처럼 하나의 객체를 계속 사용하는 방식이 아닌 호출때마다 매번 객체를 생성한다.

@PostConstruct 메서드는 스프링이 실행해주지만 그 이후의 관리는 전적으로 사용자의 몫으로 남겨진다.

그래서 @PreDestroy 메서드는 사용자가 명시적으로 호출해줘야 한다.

 

싱글톤과 프로토타입을 함께 사용하면 문제가 발생할 수 있다.

싱글톤에서 프로토타입에 대한 의존성을 갖고 있을 경우.

싱글톤 객체는 한 번만 생성되고 그 이후부터는 쭉 스프링 컨테이너에 저장되어있을뿐 새로 만들어지지 않는다.

당연히 그 안에 있는 프로토타입 빈도 의존성 주입 당시에 한 번만 생성되어 그대로 해당 객체가 유지된다. 

이는 접근할 때마다 새로운 객체를 생성한다는 프로토타입의 원래 목적에 반하는 동작이다.

(여러 종류의 싱글톤에서 한 프로토타입을 의존할 경우에는 각각 다른 프로토타입 빈이 싱글톤에 등록된다. 그 이후로 쭉 유지되는건 똑같지만)

 

이러한 문제점을 ObjectProvider<T>를 사용하여 해결할 수 있다.

private ObjectProvider<PrototypeBean> prototypeBeanProvider;
PrototypeBean prototypeBean = prototypeBeanProvider.getObject();

기존 방식처럼 생성자를 통해 DI를 실행하면 프로토타입이 프로토타입일 수 없는 문제가 발생했다.

 

ObjectProvider를 사용하여 해당 프로토타입 빈에 대한 프로바이더를 만들 수 있고, 이를 통해 getObject()로 프로토타입 빈에 접근한다.

 

이때, 미리 만들어져있는 빈을 제공하는 것이 아니라 getObject() 가 호출될 때 새 프로토타입 빈을 생성하여 반환해준다.

(getObject() 하려는 빈이 프로토타입 빈일 때만임. 사실 Provider는 프로토타입을 위한 기능이 아니라 DL을 위한 기능임)

 

즉, 호출할 때마다 매번 생성된다. 프로토타입으로서의 올바른 동작법이다. 이를 DL (Dependency Lookup) 이라고 한다.

(물론 ObjectProvider에 대한 DI는 따로 해줘야 한다.)

 

 

 

사실 프로토타입을 사용하는 일은 거의 없고 대부분이 싱글톤으로 해결된다고 한다.

+ Recent posts