복붙노트

[SPRING] @Scope ( "prototype") 빈 범위는 새 빈을 생성하지 않습니다.

SPRING

@Scope ( "prototype") 빈 범위는 새 빈을 생성하지 않습니다.

컨트롤러에 주석이 달린 프로토 타입 빈을 사용하고 싶습니다. 그러나 봄은 싱글 톤 빈을 대신 생성합니다. 그 코드는 다음과 같습니다.

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

  private int counter;

  public LoginAction(){
    System.out.println(" counter is:" + counter);
  }
  public String getStr() {
    return " counter is:"+(++counter);
  }
}

컨트롤러 코드 :

@Controller
public class HomeController {
    @Autowired
    private LoginAction loginAction;

    @RequestMapping(value="/view", method=RequestMethod.GET)
    public ModelAndView display(HttpServletRequest req){
        ModelAndView mav = new ModelAndView("home");
        mav.addObject("loginAction", loginAction);
        return mav;
    }

    public void setLoginAction(LoginAction loginAction) {
        this.loginAction = loginAction;
    }

    public LoginAction getLoginAction() {
        return loginAction;
    }
    }

속도 템플릿 :

 LoginAction counter: ${loginAction.str}

Spring config.xml에서 구성 요소 검색을 사용할 수 있습니다.

    <context:annotation-config />
    <context:component-scan base-package="com.springheat" />
    <mvc:annotation-driven />

매번 증가한 횟수가 증가하고 있습니다. 내가 어디로 잘못 가고 있는지 알 수 없다!

최신 정보

@gkamal에 의해 제안 된 것처럼, 나는 HomeController webApplicationContext-aware를 만들었고 문제를 해결했다.

업데이트 된 코드 :

@Controller
public class HomeController {

    @Autowired
    private WebApplicationContext context;

    @RequestMapping(value="/view", method=RequestMethod.GET)
    public ModelAndView display(HttpServletRequest req){
        ModelAndView mav = new ModelAndView("home");
        mav.addObject("loginAction", getLoginAction());
        return mav;
    }

    public LoginAction getLoginAction() {
        return (LoginAction) context.getBean("loginAction");
    }
}

해결법

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

    1.범위 프로토 타입은 인스턴스에 대해 봄 (getBean 또는 종속성 삽입)을 요청할 때마다 새 인스턴스를 만들고 그에 대한 참조를 제공한다는 것을 의미합니다.

    범위 프로토 타입은 인스턴스에 대해 봄 (getBean 또는 종속성 삽입)을 요청할 때마다 새 인스턴스를 만들고 그에 대한 참조를 제공한다는 것을 의미합니다.

    귀하의 예제에서 LoginAction의 새로운 인스턴스가 생성되어 HomeController에 삽입됩니다. LoginAction을 주입 할 다른 컨트롤러가있는 경우 다른 인스턴스가 생성됩니다.

    각 호출마다 다른 인스턴스를 원한다면 매번 getBean을 호출해야한다. 싱글 톤 빈에 주입하면이를 달성하지 못할 것이다.

  2. ==============================

    2.컨트롤러에 주입 된 bean이 프로토 타입 범위에 있다고해서 컨트롤러가된다는 것을 의미하지는 않는다!

    컨트롤러에 주입 된 bean이 프로토 타입 범위에 있다고해서 컨트롤러가된다는 것을 의미하지는 않는다!

  3. ==============================

    3.@controller는 싱글 톤 객체이고, 프로토 타입 빈을 싱글 톤 클래스에 삽입하면 프로토 타입 bean을 싱글 톤으로 만들 것이다. lookup-method 프로퍼티를 사용하여 실제로 호출 할 때마다 프로토 타입 빈의 새로운 인스턴스를 만든다.

    @controller는 싱글 톤 객체이고, 프로토 타입 빈을 싱글 톤 클래스에 삽입하면 프로토 타입 bean을 싱글 톤으로 만들 것이다. lookup-method 프로퍼티를 사용하여 실제로 호출 할 때마다 프로토 타입 빈의 새로운 인스턴스를 만든다.

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

    4.Spring 2.5부터는 매우 쉽고 (우아한) 방법이 있습니다.

    Spring 2.5부터는 매우 쉽고 (우아한) 방법이 있습니다.

    params proxyMode 및 @Scope 주석의 값을 변경할 수 있습니다.

    이 트릭을 사용하면 싱글 톤 빈 안에 프로토 타입이 필요할 때마다 여분의 코드를 작성하거나 ApplicationContext를 삽입하지 않아도됩니다.

    예:

    @Service 
    @Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)  
    public class LoginAction {}
    

    컨트롤러가 싱글 톤 임에도 불구하고 위의 설정을 사용하면 HomeController 내부의 LoginAction은 항상 프로토 타입입니다.

  5. ==============================

    5.nicholas.hauschild가 언급 한 것처럼 스프링 컨텍스트를 주입하는 것은 좋은 생각이 아닙니다. 귀하의 경우에는 @Scope ( "request")로 해결할 수 있습니다. 하지만 컨트롤러 메소드에서 LoginAction의 여러 인스턴스가 필요하다고 가정 해 보겠습니다. 이 경우 Supplier (스프링 4 솔루션) 빈을 만드는 것이 좋습니다.

    nicholas.hauschild가 언급 한 것처럼 스프링 컨텍스트를 주입하는 것은 좋은 생각이 아닙니다. 귀하의 경우에는 @Scope ( "request")로 해결할 수 있습니다. 하지만 컨트롤러 메소드에서 LoginAction의 여러 인스턴스가 필요하다고 가정 해 보겠습니다. 이 경우 Supplier (스프링 4 솔루션) 빈을 만드는 것이 좋습니다.

        @Bean
        public Supplier<LoginAction> loginActionSupplier(LoginAction loginAction){
            return () -> loginAction;
        }
    

    그런 다음 컨트롤러에 주입합니다.

    @Controller
    public class HomeController {
        @Autowired
        private  Supplier<LoginAction> loginActionSupplier;  
    
  6. ==============================

    6.ApplicationContextAware를 사용하면 Spring (당신이 문제 일 수도 있고 아닐 수도 있음)에 묶여있다. LoginActionFactory를 전달하는 것이 좋습니다. LoginActionFactory는 필요할 때마다 LoginAction의 새 인스턴스를 요청할 수 있습니다.

    ApplicationContextAware를 사용하면 Spring (당신이 문제 일 수도 있고 아닐 수도 있음)에 묶여있다. LoginActionFactory를 전달하는 것이 좋습니다. LoginActionFactory는 필요할 때마다 LoginAction의 새 인스턴스를 요청할 수 있습니다.

  7. ==============================

    7.@Scope ( "request")를 사용하여 각 요청에 대해 빈을 얻거나 @Scope ( "session")을 사용하여 각 세션 'user'에 대한 빈을 얻는다.

    @Scope ( "request")를 사용하여 각 요청에 대해 빈을 얻거나 @Scope ( "session")을 사용하여 각 세션 'user'에 대한 빈을 얻는다.

  8. ==============================

    8.당신의 컨트롤러는 또한 @Scope ( "prototype") 정의가 필요하다.

    당신의 컨트롤러는 또한 @Scope ( "prototype") 정의가 필요하다.

    이렇게 :

    @Controller
    @Scope("prototype")
    public class HomeController { 
     .....
     .....
     .....
    
    }
    
  9. from https://stackoverflow.com/questions/7621920/scopeprototype-bean-scope-not-creating-new-bean by cc-by-sa and MIT license