복붙노트

[SPRING] 스프링 프로토 타입 범위의 싱글 톤

SPRING

스프링 프로토 타입 범위의 싱글 톤

싱글 톤 빈에 프로토 타입 빈을 삽입하려고하는데, 싱글 톤 빈 메소드에 대한 모든 새로운 호출에는 프로토 타입 빈의 새로운 인스턴스가있다.

싱글 톤 빈을 다음과 같이 고려하십시오.

    @Component
    public class SingletonBean{

       @Autowired 
       private PrototypeBean prototypeBean;

       public void doSomething(){
         prototypeBean.setX(1);
         prototypeBean.display();
       }

    }

doSomething () 메서드가 호출 될 때마다 새로운 PrototypeBean 인스턴스가 사용되기를 기대합니다.

아래는 프로토 타입 bean입니다.

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

        Integer x;

        void setX(Integer x){
         this.x = x;
        }

        void display(){
          System.out.println(x);
        }
    }

무슨 일이 일어나는 것인가? doSomething () 메소드에서 PrototypeBean의 새로운 인스턴스를 넘겨주기 위해 봄이 열정적으로 끝나고있다. 즉, doSomething () 메소드의 코드 2 행은 각 행에 prototypeBean의 새 인스턴스를 작성합니다. 그리고 두번째 라인에서 - prototypeBean.display ()는 NULL을 출력합니다.

이것은 예상되는 동작입니까 아니면 프로토 타입 bean을 적절하게 주입하기위한 일부 구성을 놓쳤습니까?

해결법

  1. ==============================

    1.Spring 문서에서 :

    Spring 문서에서 :

    이 문서를 찾을 수있는 버전 3.2 설명서에 대한 설명서가 조금 변경된 것 같습니다.

    BeanFactory에 새로운 인스턴스를 생성 할 때마다 프록시 프로토 타입 빈을 사용할 것으로 예상되지 않습니다.

    프로토 타입 bean을위한 일종의 factory를 가지기 위해 다음과 같이 ObjectFactory를 사용할 수 있습니다 :

    @Component
    public class SingletonBean {
    
        @Autowired
        private ObjectFactory<PrototypeBean> prototypeFactory;
    
        public void doSomething() {
            PrototypeBean prototypeBean = prototypeFactory.getObject();
            prototypeBean.setX(1);
            prototypeBean.display();
        }
    }
    

    프로토 타입 빈은 다음과 같이 선언된다.

    @Component 
    @Scope(value="prototype")
    public class PrototypeBean {
        // ...
    }
    
  2. ==============================

    2.Singleton Bean은 한 번만 생성되므로 Singleton Bean의 인스턴스 생성시 한번 주입되는 Prototype Bean도 생성됩니다. 동일한 Bean 인스턴스가 모든 요청에 ​​사용됩니다.

    Singleton Bean은 한 번만 생성되므로 Singleton Bean의 인스턴스 생성시 한번 주입되는 Prototype Bean도 생성됩니다. 동일한 Bean 인스턴스가 모든 요청에 ​​사용됩니다.

    런타임시 각 요청에 대해 프로토 타입 빈의 새 인스턴스가 생성되면 아래의 메소드 삽입을 사용할 수 있습니다

    public class Singleton 
    {
        private Prototype prototype;
        public Singleton(Prototype prototype) 
        {
            this.prototype = prototype;
        }
    
        public void doSomething() 
        {
             prototype.foo();
        }
    
        public void doSomethingElse()
        {
            prototype.bar();
        }
    }
    
    public abstract class Singleton 
    {
    
        protected abstract Prototype createPrototype();
    
        public void doSomething() 
        {
            createPrototype().foo();
        }
    
        public void doSomethingElse() 
        {
            createPrototype().bar();
        }
    }
    
    
    <bean id="prototype" class="ch.frankel.blog.Prototype" scope="prototype" />
    <bean id="singleton" class="sample.MySingleton">
    <lookup-method name="createPrototype" bean="prototype" />
    </bean>
    
  3. ==============================

    3.그것을 달성하는 올바른 방법 - 조회 메소드 주입과 빈을 사용하는 모든 곳에서 lookup 메소드 호출 (상세한 답변)을 사용합니다.

    그것을 달성하는 올바른 방법 - 조회 메소드 주입과 빈을 사용하는 모든 곳에서 lookup 메소드 호출 (상세한 답변)을 사용합니다.

  4. ==============================

    4.Spring은 당신의 콩을 아주 똑바로 전진시킵니다. 대형 상용 응용 프로그램에서 작업 중이며로드 순서를 확인하기 위해 다음 코드 스 니펫을 삽입했습니다.

    Spring은 당신의 콩을 아주 똑바로 전진시킵니다. 대형 상용 응용 프로그램에서 작업 중이며로드 순서를 확인하기 위해 다음 코드 스 니펫을 삽입했습니다.

    1) 모든 싱글 톤 빈 클래스 구조는 처음에는 스프링에 의해로드됩니다 (스프링이 주석 및 / 또는 xml을 통해 스프링을 인식하는 경우). 이것은 한 번만 발생합니다. 정적 블록에 기록하거나 인쇄하여이를 테스트 할 수 있습니다.

        static {
            log.info("#### classNameHere loaded"); //or println if no log setup
        }
    

    2) Spring은 알고있는 모든 싱글 톤 인스턴스를 생성합니다 (그러나 프로토 타입은 아닙니다! 프로토 타입 인스턴스는 싱글 톤 bean 내에서 참조되는 경우 생성됩니다 - 클래스 구조가 먼저로드됩니다). 이 방법을 각 클래스에 추가하여 테스트 할 수 있습니다.

        @PostConstruct
        public void methodHitAfterClassInstantiation() {
            LOGGER.info("#### instance of classNameHere");
        }
    

    그래서 당신의 예제에서 Spring이 시작될 때 SingletonBean의 클래스 구조가로드됩니다. SingletonBean의 새로운 인스턴스가 생성됩니다. 그리고 PrototypeBean은 SingletonBean 내부에서 자동으로 실행되므로 클래스 구조가로드되고 인스턴스가 생성됩니다. 자, 내부에 Autowired PrototypeBean을 가진 AnotherSingletonBean이라고하는 또 다른 bean이 있다면 그런 다음 PrototypeBean의 다른 인스턴스가 작성됩니다 (클래스 구조를 다시로드 할 필요가 없음). 그래서 오직 하나의 SingletonBean이 있으며, 그 안에는 PrototypeBean이 있습니다. 항상 같은 빈을 가리킬 것이다. 이 때문에 싱글 톤을 사용하는 다른 모든 콩은 모두를 가리킬 것이기 때문에 싱글 톤은 항상 상태가 없어야합니다.  같은 대상. 그러나 새로운 참조를 생성하면 어디서나 다른 bean 객체를 가리킬 것이므로 prototype bean에서 상태를 유지할 수 있습니다.  http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-scopes-prototype

  5. from https://stackoverflow.com/questions/25165507/spring-prototype-scoped-bean-in-a-singleton by cc-by-sa and MIT license