수색…


싱글 톤 범위

빈이 싱글 톤 스코프로 정의되면 Spring 컨테이너에서 초기화되는 단일 객체 인스턴스 만 존재하게됩니다. 이 bean에 대한 모든 요청은 동일한 공유 인스턴스를 리턴합니다. 이것은 bean을 정의 할 때의 기본 범위입니다.

다음과 같은 MyBean 클래스가 제공됩니다.

public class MyBean {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyBean.class);
    private String property;

    public MyBean(String property) {
        this.property = property;
        LOGGER.info("Initializing {} bean...", property);
    }

    public String getProperty() {
        return this.property;
    }

    public void setProperty(String property) {
        this.property = property;
    }
}

우리는 @Bean 어노테이션으로 싱글 톤 빈을 정의 할 수있다 :

@Configuration
public class SingletonConfiguration {

    @Bean
    public MyBean singletonBean() {
        return new MyBean("singleton");
    } 
}

다음 예제는 동일한 컨텍스트를 Spring 컨텍스트에서 두 번 가져옵니다.

MyBean singletonBean1 = context.getBean("singletonBean", MyBean.class);
singletonBean1.setProperty("changed property");

MyBean singletonBean2 = context.getBean("singletonBean", MyBean.class);

singletonBean2 속성을 로깅 할 때 동일한 공유 인스턴스를 검색했기 때문에 "changed property" 메시지가 표시됩니다.

인스턴스가 여러 구성 요소간에 공유되므로 상태 비 저장 객체에 대한 단일 범위를 정의하는 것이 좋습니다.

게으른 싱글 톤 콩

기본적으로 싱글 톤 bean은 사전 인스턴스화됩니다. 따라서 Spring 객체가 생성 될 때 공유 객체 인스턴스가 생성 될 것이다. 응용 프로그램을 시작하면 "Singleton Bean 초기화 중 ..." 메시지가 표시됩니다.

빈이 미리 인스턴스화되는 것을 원하지 않는다면 @Lazy 주석을 빈 정의에 추가 할 수있다. 이렇게하면 bean이 처음 요청 될 때까지 bean이 작성되지 않습니다.

@Bean
@Lazy
public MyBean lazySingletonBean() {
    return new MyBean("lazy singleton");
}

이제 Spring 컨테이너를 시작하면 "Initializing lazy singleton bean ..." 메시지가 나타나지 않습니다. Bean은 처음 요청 될 때까지 작성되지 않습니다.

logger.info("Retrieving lazy singleton bean...");
context.getBean("lazySingletonBean");

싱글 톤 bean과 lazy 싱글 톤 bean을 모두 정의하여 응용 프로그램을 실행하면 다음 메시지가 생성됩니다.

Initializing singleton bean...
Retrieving lazy singleton bean...
Initializing lazy singleton bean...

프로토 타입 범위

프로토 타입 범위의 빈은 Spring 컨테이너 시작시 미리 생성되지 않는다. 대신이 빈을 검색하라는 요청이 컨테이너에 보내질 때마다 새로운 새로운 인스턴스가 생성 될 것이다. 이 범위는 상태가 다른 객체와 공유되지 않으므로 상태 객체에 권장됩니다.

프로토 타입 범위 Bean을 정의하려면 @Scope 주석을 추가하여 원하는 범위 유형을 지정해야합니다.

다음과 같은 MyBean 클래스가 제공됩니다.

public class MyBean {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyBean.class);
    private String property;

    public MyBean(String property) {
        this.property = property;
        LOGGER.info("Initializing {} bean...", property);
    }

    public String getProperty() {
        return this.property;
    }

    public void setProperty(String property) {
        this.property = property;
    }
}

우리는 범위를 프로토 타입으로 명시한 bean 정의를 정의합니다.

@Configuration
public class PrototypeConfiguration {

    @Bean
    @Scope("prototype")
    public MyBean prototypeBean() {
        return new MyBean("prototype");
    }
}

어떻게 작동하는지보기 위해 Spring 컨테이너에서 빈을 검색하고 속성 필드에 다른 값을 설정합니다. 다음으로, 다시 컨테이너에서 빈을 검색하여 값을 찾습니다.

MyBean prototypeBean1 = context.getBean("prototypeBean", MyBean.class);
prototypeBean1.setProperty("changed property");

MyBean prototypeBean2 = context.getBean("prototypeBean", MyBean.class);

logger.info("Prototype bean 1 property: " + prototypeBean1.getProperty());
logger.info("Prototype bean 2 property: " + prototypeBean2.getProperty());

다음 결과를 보면 각 빈 요청에 대해 새 인스턴스가 생성 된 방법을 알 수 있습니다.

Initializing prototype bean...
Initializing prototype bean...
Prototype bean 1 property: changed property
Prototype bean 2 property: prototype

일반적인 실수는 bean이 호출에 따라 재 작성 또는 스레드 당, 이러한 경우가 있다고 가정하는 것입니다. 대신 인스턴스가 PER INJECTION (또는 컨텍스트에서 검색)으로 작성됩니다. Prototype Scoped Bean이 하나의 Singleton Bean에만 삽입된다면, 그 Prototype Scoped Bean의 인스턴스가 하나만있을 것입니다.

Spring은 프로토 타입 빈의 전체 라이프 사이클을 관리하지 않습니다. 컨테이너는 프로토 타입 객체를 인스턴스화, 구성, 장식 및 조립하여 클라이언트에게 전달한 다음 해당 프로토 타입 인스턴스를 더 이상 알지 못합니다.

웹 인식 컨텍스트의 추가 범위

웹 인식 응용 프로그램 컨텍스트에서만 사용할 수있는 여러 가지 범위가 있습니다.

  • request - HTTP 요청마다 새로운 빈 인스턴스가 생성됩니다.
  • session - HTTP 세션 당 새로운 빈 인스턴스가 생성됩니다.
  • application - ServletContext 마다 새로운 bean 인스턴스 생성
  • globalSession - 포틀릿 환경에서 전역 세션마다 새 빈 인스턴스가 생성됩니다 (서블릿 환경에서는 전역 세션 범위가 세션 범위와 같습니다)
  • websocket - WebSocket 세션마다 새로운 빈 인스턴스가 생성됩니다.

스프링 웹 MVC 환경에서 웹 스코프 된 빈을 선언하고 액세스하는 데 추가 설정이 필요하지 않습니다.

XML 구성

<bean id="myRequestBean" class="OneClass" scope="request"/>
<bean id="mySessionBean" class="AnotherClass" scope="session"/>
<bean id="myApplicationBean" class="YetAnotherClass" scope="application"/>
<bean id="myGlobalSessionBean" class="OneMoreClass" scope="globalSession"/>

자바 설정 (Spring 4.3 이전)

@Configuration
public class MyConfiguration {

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public OneClass myRequestBean() {
        return new OneClass();
    }

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public AnotherClass mySessionBean() {
        return new AnotherClass();
    }

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public YetAnotherClass myApplicationBean() {
        return new YetAnotherClass();
    }

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_GLOBAL_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public OneMoreClass myGlobalSessionBean() {
        return new OneMoreClass();
    }
}

자바 설정 (Spring 4.3 이후)

@Configuration
public class MyConfiguration {

    @Bean
    @RequestScope
    public OneClass myRequestBean() {
        return new OneClass();
    }

    @Bean
    @SessionScope
    public AnotherClass mySessionBean() {
        return new AnotherClass();
    }

    @Bean
    @ApplicationScope
    public YetAnotherClass myApplicationBean() {
        return new YetAnotherClass();
    }
}

주석 기반 구성 요소

@Component
@RequestScope
public class OneClass {
    ...
}

@Component
@SessionScope
public class AnotherClass {
    ...
}

@Component
@ApplicationScope
public class YetAnotherClass {
    ...
}

@Component
@Scope(scopeName = WebApplicationContext.SCOPE_GLOBAL_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class OneMoreClass {
    ...
}

@Component
@Scope(scopeName = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class AndOneMoreClass {
    ...
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow