# Spring / Bean Scope
Study Repository

Spring / Bean Scope

by rlaehddnd0422

๋นˆ ์Šค์ฝ”ํ”„

: ๋นˆ์ด ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์—์„œ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ”์œ„

 

์ง€๊ธˆ๊นŒ์ง€ ์Šคํ”„๋ง ๋นˆ์ด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์‹œ์ž‘๊ณผ ํ•จ๊ป˜ ์ƒ์„ฑ๋˜์—ˆ๋‹ค๊ฐ€ ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ข…๋ฃŒ๋ ๋•Œ๊นŒ์ง€ ์œ ์ง€๋œ๋‹ค๊ณ  ๋ฐฐ์› ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ์Šคํ”„๋ง ๋นˆ์ด ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ์ƒ์„ฑ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

์Šคํ”„๋ง ๋นˆ์—๋Š” ์‹ฑ๊ธ€ํ†ค๊ณผ ํ”„๋กœํ† ํƒ€์ž…์ด ์žˆ๋‹ค.

 

์‹ฑ๊ธ€ํ†ค : ๊ธฐ๋ณธ ๋นˆ, ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ์‹œ์ž‘๊ณผ ํ•จ๊ป˜ ์ƒ์„ฑ -> ์ปจํ…Œ์ด๋„ˆ ์ข…๋ฃŒ์ง์ „์— ์†Œ๋ฉธ๋จ.

ํ”„๋กœํ† ํƒ€์ž… : ๋นˆ์˜ ์ƒ์„ฑ๊ณผ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…๊นŒ์ง€๋งŒ ์œ ์ง€๋˜๋Š” ๋นˆ. ์ด ์ดํ›„์—๋Š” ์ปจํ…Œ์ด๋„ˆ์—์„œ ๊ด€๋ฆฌ๋˜์ง€ ์•Š๋Š”๋‹ค.

 

๋นˆ ์Šค์ฝ”ํ”„๋Š” @Scope๋ฅผ ํ†ตํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

@Scope("prototype") -> ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„

@Scope("singleton") -> ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„

 

 

@Component๋ฅผ ์ด์šฉํ•œ ์ž๋™๋“ฑ๋ก

@Scope("prototype")
@Component
public class HelloBean{}

 

์ˆ˜๋™ ๋“ฑ๋ก 

@Scope("prototype")
@Bean
ProtoTypeBean HelloBean()
{
	return new HelloBean();
}

  ์ง€๊ธˆ๊นŒ์ง€๋Š” ๊ณ„์† ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์•˜์œผ๋‹ˆ, ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์ž

 


ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„

์‹ฑ๊ธ€ํ†ค์˜ ๊ฒฝ์šฐ ํ•ญ์ƒ ๊ฐ™์€ ์ธ์Šคํ„ด์Šค์˜ ์Šคํ”„๋ง ๋นˆ์„ ๋ฆฌํ„ดํ•œ๋‹ค.

ํ•˜์ง€๋งŒ ํ”„๋กœํ† ํƒ€์ž…์€ ํ•ญ์ƒ ์ƒˆ๋Ÿฌ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋ฆฌํ„ดํ•œ๋‹ค. ( ์—„๋ฐ€ํžˆ ๋งํ•˜๋ฉด ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ํ›„ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…๊นŒ์ง€ ๋งˆ์นœ ํ›„ ๋ฆฌํ„ด )

1. ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„์˜ ๋นˆ์„ ์ปจํ…Œ์ด๋„ˆ์— ์š”์ฒญ

2. ์ด ์‹œ์ ์— ํ•ญ์ƒ ์ƒˆ๋กœ์šด ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ์ƒ์„ฑํ•˜๊ณ  ์˜์กด๊ด€๊ณ„๋ฅผ ์ฃผ์ž…ํ•œ๋‹ค.

3. ํด๋ผ์ด์–ธํŠธ์— ๋ฆฌํ„ด

4. ๋ฆฌํ„ด ์ดํ›„์—๋Š” ์ปจํ…Œ์ด๋„ˆ์—์„œ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

์—ฌ๊ธฐ์„œ ํ•ต์‹ฌ์€ ์ปจํ…Œ์ด๋„ˆ๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ์ƒ์„ฑ -> DI -> ์ดˆ๊ธฐํ™” ๊นŒ์ง€๋งŒ ์ฒ˜๋ฆฌ.

๋นˆ์„ ๋ฆฌํ„ดํ›„์—๋Š” ์ปจํ…Œ์ด๋„ˆ์—์„œ ๊ด€๋ฆฌ X!!

๊ทธ๋ž˜์„œ @PreDestroy๊ฐ™์€ ์ข…๋ฃŒ ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š์Œ.

 

TestCode

package hello.core.scope;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class PrototypeTest {

    @Test
    void prototypeBeanTest()
    {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ProtoTypeBean.class);
        System.out.println("find prototypeBean1");
        ProtoTypeBean protoTypeBean1 = ac.getBean(ProtoTypeBean.class);
        System.out.println("find prototypeBean2");

        ProtoTypeBean protoTypeBean2 = ac.getBean(ProtoTypeBean.class);


        System.out.println("protoTypeBean1 = " + protoTypeBean1);
        System.out.println("protoTypeBean2 = " + protoTypeBean2);

        Assertions.assertThat(protoTypeBean1).isNotSameAs(protoTypeBean2);

        ac.close();
    }

    @Scope("prototype")
    static class ProtoTypeBean
    {
        @PostConstruct
        public void init()
        {
            System.out.println("ProtoTypeBean.init");
        }

        @PreDestroy
        public void destroy()
        {
            System.out.println("ProtoTypeBean.destroy");
        }
    }
}

์ข…๋ฃŒ ๋ฉ”์†Œ๋“œ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์Œ.

๊ฐ์ฒด์ •๋ณด๋ฅผ ๋ณด๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ์ฃผ์†Œ๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์€ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ƒ์„ฑ๊ณผ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… ๊ทธ๋ฆฌ๊ณ  ์ดˆ๊ธฐํ™” ๊นŒ์ง€๋งŒ ๊ด€์—ฌํ•˜๊ณ , ๋”๋Š” ๊ด€๋ฆฌํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋”ฐ๋ผ์„œ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์€ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ @PreDestroy ๊ฐ™์€ ์ข…๋ฃŒ ๋ฉ”์„œ๋“œ๊ฐ€ ์ „ํ˜€ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.

 

ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์˜ ํŠน์ง•

1. ์ปจํ…Œ์ด๋„ˆ์— ์š”์ฒญ๋  ๋•Œ ๋งˆ๋‹ค ์ƒˆ๋กœ ์ƒ์„ฑ๋œ๋‹ค.

2. ์ปจํ…Œ์ด๋„ˆ๋Š” ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์˜ ์ƒ์„ฑ, DI, ์ดˆ๊ธฐํ™”๊นŒ์ง€๋งŒ ๊ด€์—ฌํ•œ๋‹ค.

3. ์ข…๋ฃŒ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š์Œ

4. ๊ทธ๋ž˜์„œ ํ”„๋กœํ† ํƒ€์ž…๋นˆ์€ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ์กฐํšŒํ•œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.

 


ํ”„๋กœํ† ํƒ€์ž… - ์‹ฑ๊ธ€ํ†ค ํ•จ๊ป˜ ์‚ฌ์šฉ ์‹œ ๋ฌธ์ œ์ 

 

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž.

 

1. SpringContainer๋‚ด๋ถ€์— SingletonBean, ProtoTypeBean ์ƒ์„ฑ

2. Singleton -> ProtoTypeBean ์˜์กด @Autowired

3. ClientA๊ฐ€ login() ํ˜ธ์ถœํ•œ ๋’ค ClientB๊ฐ€ logic()์„ ํ˜ธ์ถœํ•œ ๋’ค์˜ count ๊ฐ’์€ ๋ช‡์ผ๊นŒ? 

 

 

TestCode

package hello.core.scope;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Scope;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class SingletoneWithProtoTypeTest {

    @Test
    void singleWithProto()
    {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SingletonBean.class, ProtoTypeBean.class);

        SingletonBean bean = ac.getBean(SingletonBean.class);
        SingletonBean bean2 = ac.getBean(SingletonBean.class);

        int count1 = bean.logic();
        int count2 = bean2.logic();

        System.out.println("count1 = " + count1);
        System.out.println("count2 = " + count2);

    }

    @Scope("singleton")
    static class SingletonBean
    {
        private final ProtoTypeBean protoTypeBean;

        @Autowired
        public SingletonBean(ProtoTypeBean protoTypeBean) {
            this.protoTypeBean = protoTypeBean;
        }

        public int logic()
        {
            protoTypeBean.addCount();
            return protoTypeBean.getCount();
        }

        @PostConstruct
        public void init()
        {
            System.out.println("SingletonBean.init");
        }

        @PreDestroy
        public void destroy()
        {
            System.out.println("SingletonBean.destroy");
        }

    }
    @Scope("prototype")
    static class ProtoTypeBean
    {
        private int count = 0;

        public void addCount()
        {
            count++;
        }

        public int getCount()
        {
            return this.count;
        }

        @PostConstruct
        public void init()
        {
            System.out.println("ProtoTypeBean.init");
        }
        @PreDestroy
        public void destroy()
        {
            System.out.println("ProtoTypeBean.destroy");
        }
    }
}

Testcode ๊ฒฐ๊ณผ

ํด๋ผ์ด์–ธํŠธB๋Š” SingletoneBean์„ ์ปจํ…Œ์ด๋„ˆ์— ์š”์ฒญํ•ด์„œ ๋ฐ›๋Š”๋‹ค. ์‹ฑ๊ธ€ํ†ค์ด๋ฏ€๋กœ ํ•ญ์ƒ ๊ฐ™์€ SingletonBean์ด ๋ฐ˜ํ™˜๋œ๋‹ค.

 

์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ์ ์€ SingletonBean์ด ๋‚ด๋ถ€์— ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ProtoTypeBean

์€ ์ด๋ฏธ Client A์—์„œ ์ฃผ์ž…์ด ๋๋‚œ ๋นˆ์ด๋‹ค. ์ฃผ์ž… ์‹œ์ ์— ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์š”์ฒญํ•ด์„œ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์ด ์ƒˆ๋กœ ์ƒ์„ฑ์ด ๋œ ๊ฒƒ์ด์ง€, ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ClientB๋Š” A๊ฐ€ ์š”์ฒญํ•œ count๊ฐ’์—์„œ 1 ์ฆ๊ฐ€ํ•˜์—ฌ 2๊ฐ€ ๋œ๋‹ค.

 

์Šคํ”„๋ง์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์‹ฑ๊ธ€ํ†ค ๋นˆ์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์‹ฑ๊ธ€ํ†ค ๋นˆ์ด ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋จ.

๊ทธ๋Ÿฐ๋ฐ ์‹ฑ๊ธ€ํ†ค ๋นˆ์€ ์ƒ์„ฑ ์‹œ์ ์—๋งŒ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์„ ๋ฐ›๊ธฐ ๋–„๋ฌธ์—, ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์ด ์ƒˆ๋กœ ์ƒ์„ฑ๊ธฐ๋Š” ํ•˜์ง€๋งŒ, ์‹ฑ๊ธ€ํ†ค ๋นˆ๊ณผ ํ•จ๊ป˜ ๊ณ„์† ์œ ์ง€๋œ๋‹ค๋Š” ๊ฒƒ์ด ๋ฌธ์ œ๋‹ค.

 


Provider๋ฅผ ์ด์šฉํ•œ ์˜์กด๊ด€๊ณ„ ์กฐํšŒ (DL)

์šฐ์„  ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์€ ์‹ฑ๊ธ€ํ†ค ๋นˆ์ด ํ”„๋กœํ† ํƒ€์ž…์„ ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์ƒˆ๋กœ ์š”์ฒญํ•˜๋Š” ๊ฒƒ์ด๋‹ค

 

์ฝ”๋“œ๋กœ ์•Œ์•„๋ณด์ž

@Scope("singleton")
static class ClientBean
{
    @Autowired private ApplicationContext ac;

    public int logic()
    {
        PrototypeBean bean = ac.getBean(PrototypeBean.class);
        bean.addcount();
        return bean.getCount();
    }
}

 

์‹คํ–‰ํ•ด๋ณด๋ฉด ac.getBean์„ ํ†ตํ•ด ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ํ•ญ์ƒ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์˜์กด๊ด€๊ณ„๋ฅผ ์™ธ๋ถ€์—์„œ ์ฃผ์ž…๋ฐ›๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ์ง์ ‘ ํ•„์š”ํ•œ ์˜์กด๊ด€๊ณ„๋ฅผ ์ฐพ๋Š” ๊ฒƒ์„ DL(์˜์กด๊ด€๊ณ„ ์กฐํšŒ)๋ผ ํ•œ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ด๋ ‡๊ฒŒ Application context ์ „์ฒด๋ฅผ ์ฃผ์ž…๋ฐ›๊ฒŒ ๋˜๋ฉด, ์ปจํ…Œ์ด๋„ˆ์— ์ข…์†์ ์ธ ์ฝ”๋“œ๊ฐ€ ๋˜๊ณ , ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ์–ด๋ ค์›Œ์ง.

 

 

์ง€๊ธˆ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ : ์ง€์ •ํ•œ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ์ปจํ…Œ์ด๋„ˆ์—์„œ ๋Œ€์‹  ์ฐพ์•„์ฃผ๋Š” ๋”ฑ DL์ •๋„์˜ ๊ธฐ๋Šฅ๋งŒ ์ œ๊ณตํ•˜๋Š” ๋ฌด์–ธ๊ฐ€๊ฐ€ ํ•„์š”.

โ–ถ๏ธŽ ObjectFactory, ObjectProvider

 

์ง€์ •ํ•œ ๋นˆ์„ ์ปจํ…Œ์ด๋„ˆ์—์„œ ๋Œ€์‹  ์ฐพ์•„์ฃผ๋Š” DL ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ ObjectProvider

 

ObjectProvider๋ฅผ ์‚ฌ์šฉํ•œ ์˜ˆ์‹œ

    @Scope("singleton")
    static class ClientBean
    {
//        @Autowired private ApplicationContext ac;

        @Autowired
        private ObjectProvider<PrototypeBean> prototypeBeanProvider;

        public int logic()
        {
//            PrototypeBean bean = ac.getBean(PrototypeBean.class);
            PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
            prototypeBean.addcount();
            return prototypeBean.getCount();
        }
    }

 

์‹คํ–‰ํ•ด๋ณด๋ฉด prototypeBeanProvider.getObject()๋ฅผ ํ†ตํ•ด์„œ ํ•ญ์ƒ ์ƒˆ๋กœ์šด ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์ด ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

ObejctProvider์˜ getObejct()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋‚ด๋ถ€์—์„œ๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ๋นˆ์„ ์ฐพ์•„์„œ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

 

ObejctFactory ๋˜ํ•œ ๋งˆ์ฐฌ๊ฐ€์ง€

    @Scope("singleton")
    static class ClientBean
    {
//        @Autowired private ApplicationContext ac;

//        @Autowired
//        private ObjectProvider<PrototypeBean> prototypeBeanProvider;

        @Autowired
        private ObjectFactory<PrototypeBean> prototypeBeanObjectFactory;

        public int logic()
        {
//            PrototypeBean bean = ac.getBean(PrototypeBean.class);
//            PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
            PrototypeBean prototypeBean = prototypeBeanObjectFactory.getObject();
            prototypeBean.addcount();
            return prototypeBean.getCount();
        }
    }

์ฐจ์ด์ 

ObjectFactory : ๊ธฐ๋Šฅ์ด ๋‹จ์ˆœ, ๋ณ„๋„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ•„์š” ์—†์Œ, ์Šคํ”„๋ง์— ์˜์กด

ObjectProvider : ObjectFactory ์ƒ์†, ์˜ต์…˜, ์ŠคํŠธ๋ฆผ ์ฒ˜๋ฆฌ๋“ฑ ํŽธ์˜ ๊ธฐ๋Šฅ์ด ๋งŽ๊ณ , ๋ณ„๋„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ•„์š” ์—†์Œ, ์Šคํ”„๋ง์— ์˜์กด

 

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ์ž๋ฐ” ํ‘œ์ค€ DL๋„ ์žˆ๋‹ค โ–ถ๏ธŽ JSR-330 Provider

 

 

 

 

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

Study Repository

rlaehddnd0422

ํ™œ๋™ํ•˜๊ธฐ