Java/Spring framework

Spring framework core (3) - Bean scope

감동이중요해 2020. 1. 12. 22:15

IoC Container - Bean의 Scope

Scope type

  1. Singleton (Default)

    • App에서 1개의 인스턴스만 존재
  2. Proto

    • 매번 다른 인스턴스 생성

Singleton과 Proto를 만들어서 눈으로 확인해보자.
의존성 없이 사용할 땐 별다른 문제가 없지만,
Singleton과 Proto 사이 의존 관계가 있다면 의도대로 작동하지 않을 수 있다.

Example 1

  1. Singleton
@Component
class Singleton { }
  1. Prototype
@Component @Scope(“prototype”)
class Prototype { }
  1. AppRunner (결과 확인용)
@Component
public class AppRunner implements ApplicationRunner {

    @Autowired Singleton singleton;
    @Autowired Prototype prototype;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(singleton);
        System.out.println(singleton);

        System.out.println(prototype);
        System.out.println(prototype);
    }
}
  • ApplicationRunner는 프로그램이 구동되면 run 메소드를 실행한다.

위의 코드를 실행하면 아래와 같은 결과를 볼 수 있다.

com.example.demo.Singleton@6e01f9b0
com.example.demo.Singleton@6e01f9b0
com.example.demo.Prototype@658c5a19
com.example.demo.Prototype@421e361

Singleton은 같은 인스턴스, Prototype은 매번 다른 인스턴스를 생성한다.

Example 2

위의 코드에서 Singleton, AppRunner를 약간 변형한다.

  1. Singleton이 Prototype를 의존하도록 하였다.
@Component
public class Singleton {

    @Autowired private Prototype prototype;

    public Prototype getPrototype() {
        return prototype;
    }
}
  1. AppRunner에서는 Prototype 출력 부분을 변경했다.
@Component
public class AppRunner implements ApplicationRunner {

    @Autowired Singleton singleton;

    @Autowired Prototype prototype;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(singleton);
        System.out.println(singleton);

        System.out.println(singleton.getPrototype());
        System.out.println(singleton.getPrototype());
    }
}

Example 1과 같은 결과가 나와야 할 것 같지만 전혀 다르게 동작한다.

com.example.demo.Singleton@a307a8c
com.example.demo.Singleton@a307a8c
com.example.demo.Prototype@6e01f9b0
com.example.demo.Prototype@6e01f9b0

Singleton에서 의존하는 Prototype은 마치 Singleton처럼 작동하고 있다.

아래의 Example 3는 위의 Prototype을 원래 생각하던 것처럼 작동하게 만드는 예제이다.

Example 3

Singleton과 의존 관계에 있는 Prototype을 의도대로 작동시키기 위해 코드를 약간 수정한다.

@Component
@Scope(value = “prototype”, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Prototype { }

다시 실행시키면 Singleton에서 참조하는 Prototype도 매번 변경됨을 확인할 수 있다.

com.example.demo.Singleton@3406472c
com.example.demo.Singleton@3406472c
com.example.demo.Prototype@7cbd9d24
com.example.demo.Prototype@1672fe87

원리는 proxy 패턴이다.

본래 Singleton -> Prototype의 관계였으나 proxy가 관여하여 Singleton -> proxy -> Prototype 관계로 바뀌게 된다.

Singleton이 Spring에 의해 생성된 proxy를 참조하고, proxy는 매번 다른 Prototype을 생성하여 반환한다.

 

 

작성한 소스코드는 아래 링크에서 볼 수 있다.

https://github.com/dhmin5693/Spring-core-study/tree/master/BeanScope