개발자 미니민의 개발스터디

[spring] bean Scopes 빈 객체 범위 정의

by mini_min
[spring] bean Scopes 빈 객체 범위 정의

✔️ 스프링 빈 스코프

: Bean 정의를 통해 객체의 종속성, 설정 값을 줄 수 있을 뿐만 아니라 객체의 범위도 정의할 수 있다.

기본적으로 스프링은 모든 Bean 을 singleton 으로 생성 및 관리한다.

 

📓 스프링 프레임워크 6가지 scope 

- singleton : 스프링 컨테이너에 한 개의 빈 인스턴스만 생성 (기본)

- prototype : 스프링 컨테이너에 빈을 요청할 때 마다 새로운 빈 인스턴스 생성

- request : HTTP 요청 마다 빈 객체 생성 (WebApplicationContext 에서만 적용)

- session : HTTP 세션 마다 빈 객체 생성 (WebApplicationContext 에서만 적용)

- application : 웹 응용 프로그램에 대하여 하나의 객체만 생성 (WebApplicationContext 에서만 적용)

- websocket : 전체 수명주기 동안 단일 인스턴스가 생성

 

 

✔️ Bean Scope 설정

: <bean> 태그의 scope 속성을 이용해서 빈의 범위를 설정한다.

scope = 빈범위

 

-- 예시

-- applicationContext.xml

<!--  scope : 기본 - singleton : 하나의 객체만 생성한다. -->
<bean id="movie" class="com.scope1.Movie" />

<!-- prototype : 빈에서 객체를 호출할 때 마다 객체가 생성된다. -->
<bean id="music" class="com.scope1.Music" scope="prototype"/>

 

-- 자바 App 실행 파일

✨ prototype 은 컨테이너에서 빈을 가져올 때마다 객체 생성하여 다운 캐스팅해준다. 

✨ 기본 singleton 의 경우 다운 캐스팅할 필요가 없다.

public static void main(String[] args) {
    AbstractApplicationContext context = 
            new GenericXmlApplicationContext("classpath:com/scope1/applicationContext.xml");

    try {
        // 다운 캐스팅 할 필요가 없다. 
        Movie movie1 = context.getBean(Movie.class);
        Movie movie2 = context.getBean(Movie.class);

        // 기본 : singleton
        if(movie1== movie2) {
            System.out.println("movie : 동일한 객체 ");
        } else {
            System.out.println("movie : 다른 객체");
        }

        movie1.play();
        movie2.play();
        System.out.println("----------------------");

        //prototype : 컨테이너에서 빈을 가져올 때마다 객체 생성한다.
        Music music1 = (Music)context.getBean("music");
        Music music2 = (Music)context.getBean("music");

        if(music1== music2) {
            System.out.println("music : 동일한 객체 ");
        } else {
            System.out.println("music : 다른 객체");
        }

        music1.play();
        music2.play();
        System.out.println("----------------------");

    } finally {
        context.close();
    }


}

 

✔️ <aop:scoped-proxy/>

: 생명주기가 더 짧은 bean 을 생명주기가 더 긴 bean 에 주입하면 문제가 생긴다.

이러한 문제를 해결하기 위해 스프링 프레임워크는 프록시 빈이라는 개념을 제공한다. 

 

📓 proxy-target-class 속성

: 해당 속성을 false 로 하면 스프링 컨테이너는 표준 JDK 인터페이스 기반 프록시를 생성한다.

 

📓 prototype scope bean 에서 설정

: 공유된 proxy 에서 메소드 호출이 일어날 때 마다 새로운 타겟 instance 가 생성되고 호출이 해당 instance 로 포워딩된다.

 

📓 request 나 session bean 에서 설정

: request 나 session bean 의 실제 인스턴스가 아닌 Proxy 객체를 주입하여 request 나 session bean 마다 생성되는 빈을 참조한다.

 

👩‍💻 프록시 패턴이란?

: 실제 기능을 수행하는 객체 대신, 가상의 객체를 사용해서 로직의 흐름을 제어하는 디자인 패턴이다.

 

📓 프록시 패턴의 특징

- 원래 하려던 기능을 수행하며 그 외의 부가적인 작업 등을 수행할 수 있다.

- 비용이 많이 드는 연산을 실제로 필요한 시점에 수행할 수 있다.

- 사용자 입장에서는 프록시 객체나 사용법은 유사하므로 사용성이 좋다.

 

-- 예시

-- applicationContext.xml

✨ music 은 <aop:scoped-proxy/> 설정하여 다른 객체들이 나온다.

<bean id="movie" class="com.scope2.Movie" scope="prototype"/>

<bean id="music" class="com.scope2.Music" scope="prototype">
    <aop:scoped-proxy/>
    <!-- <aop:scoped-proxy/> : 다른 객체들이 나옴 -->
</bean>


<bean id="user" class="com.scope2.User">
    <property name="movie" ref="movie"/>
    <property name="music" ref="music"/>
</bean>
public static void main(String[] args) {
    AbstractApplicationContext context = 
            new GenericXmlApplicationContext("classpath:com/scope2/applicationContext.xml");

    try {
        User user = context.getBean(User.class);

        user.execute();
        user.execute();
        user.execute(); // movie는 동일객체, music는 다른 객체 
        System.out.println("-------------------");

        Movie movie = context.getBean(Movie.class);
        Music music = context.getBean(Music.class);

        movie.play();
        movie.play(); // 같은 객체
        System.out.println("-------------------");

        music.play();
        music.play(); // 다른 객체 

    } finally {
        context.close();
    }


}

movie는 동일객체, music는 다른 객체

 

 

 

 

블로그의 정보

개발자 미니민의 개발로그

mini_min

활동하기