본문 바로가기

Spring/Spring

(SPRING) IoC 컨테이너 - 빈의 스코프

스코프

싱글톤 - Application 전반에 걸쳐서 해당 Bean의 인스턴스가 오직 한 개뿐

 

Single은 Proto를 주입받는다.

@Component
public class Single {

    @Autowired
    Proto proto;

    public Proto getProto() {
        return proto;
    }
}

System.out.println(proto);   :  AppRunner의 Proto
System.out.println(single.getProto()); : Single의 Proto

public class AppRunner implements ApplicationRunner {
    @Autowired
    Single single;

    @Autowired
    Proto proto;

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


    }
}

 

 

실행결과 각각의 프로토가 같은 해시 코드인 것을 확인할 수 있다.

 

 


프로토타입 - 매번 새로운 인스턴스를 만들어서 사용하는 scope

 

Scope prototype으로 지정

@Component @Scope("prototype")
public class Proto {
}
@Component
public class AppRunner implements ApplicationRunner {

    @Autowired
    ApplicationContext ctx;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("single");
        System.out.println(ctx.getBean(Single.class));
        System.out.println(ctx.getBean(Single.class));
        System.out.println(ctx.getBean(Single.class));
        
        System.out.println("proto");
        System.out.println(ctx.getBean(Proto.class));
        System.out.println(ctx.getBean(Proto.class));
        System.out.println(ctx.getBean(Proto.class));
    }
}

 

 

 

prototype은 각각의 다른 해시 코드가 출력된다.

 

 

 


Prototype의 Scope 이 Singletontype의 Scope을 사용하는 경우 

- 아무 문제가 없다

- Prototype의 Scope 매번 다른 인스턴스를 생성하지만 Singletontype의 Scope은 하나의 인스턴스를 참조하기 때문에 상관없다.

@Component @Scope("prototype")
public class Proto {

    @Autowired
    Single single;
}

 

Singletontype의 ScopePrototype의 Scope을 사용하는 경우 

@Component
public class Single {

    @Autowired
    Proto proto;

    public Proto getProto() {
        return proto;
    }
}
@Component
public class AppRunner implements ApplicationRunner {

    @Autowired
    ApplicationContext ctx;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("single");
        System.out.println(ctx.getBean(Single.class));
        System.out.println(ctx.getBean(Single.class));
        System.out.println(ctx.getBean(Single.class));

        System.out.println("proto");
        System.out.println(ctx.getBean(Proto.class));
        System.out.println(ctx.getBean(Proto.class));
        System.out.println(ctx.getBean(Proto.class));

        System.out.println("proto by single");
        System.out.println(ctx.getBean(Single.class).getProto());
        System.out.println(ctx.getBean(Single.class).getProto());
        System.out.println(ctx.getBean(Single.class).getProto());
    }
}

 

 

 

 

Prototype의 해시 코드가 의도와는 다르게 바뀌지 않는다.

 

 

 

 

 

 

해결방법 1. ProxyMode의 사용

 

프락시로 Proto를 감싸는 이유는

Single이 Proto 타입의 빈을 직접 참조하면 안 되기 때문에

 

직접 참조해버리면 Proto는 매번 같은 인스턴스를 가지므로

Proxy로 감싸버린다. (with cglib)

 

 

 

https://jwdeveloper.tistory.com/47?category=823919

 

(JAVA) 다이나믹 프록시

다이내믹 프록시란? 런타임 시점에(컴파일 시점이 아닌) 특정 인터페이스들을 구현하는 클래스 혹은 인스턴스를 만드는 기술 https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html Dyna..

jwdeveloper.tistory.com

@Component @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Proto {

}

Proxy 인스턴스가 Bean으로 등록

해당 Proxy Bean을

@Autowired
   Proto proto;

에 주입 (타입이 같기 때문에 주입이 가능하다.)

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

 

Proxy pattern - Wikipedia

In computer programming, the proxy pattern is a software design pattern. A proxy, in its most general form, is a class functioning as an interface to something else. The proxy could interface to anything: a network connection, a large object in memory, a f

en.wikipedia.org

 

해결방법 2.ObjectProvider의 사용

@Component
public class Single {

    @Autowired
    private ObjectProvider<Proto> proto;

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

코드참조

https://github.com/mike6321/Spring/tree/master/Spring/demospring51

 

mike6321/Spring

Contribute to mike6321/Spring development by creating an account on GitHub.

github.com