156 votes

La portée du bean @Scope ("prototype") ne crée pas de nouveau bean

Je veux utiliser un annotée prototype de haricots dans mon contrôleur. Mais le printemps est la création d'un singleton de haricots à la place. Voici le code pour que:

@Component
@Scope("prototype")
public class LoginAction {
private int counter;
  public LoginAction(){
    System.out.println(" counter is:" + counter);
  }
  public String getStr() {
    return " counter is:"+(++counter);
  }
}

Contrôleur de code:

@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;
}

Vitesse modèle:

 LoginAction counter: ${loginAction.str}

printemps config.xml a composant de balayage activé:

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

Je suis un incrémenté de compter à chaque fois. Ne pouvez pas comprendre où je suis, va pas!!!

Mise à jour

Comme suggéré par @gkamal fait le contrôleur HomeController webApplicationContext conscient et il a résolu le problème.

mise à jour du Contrôleur de code:

@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", loginAction);
    return mav;
}

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

188voto

gkamal Points 9679

Portée prototype signifie que chaque fois que vous demandez printemps (getBean ou l'injection de dépendance) pour un exemple, il va créer une nouvelle instance et de donner une référence à cela.

Dans votre exemple, une nouvelle instance de LoginAction est créé et injecté dans votre contrôleur HomeController . Si vous avez un autre contrôleur dans lequel vous injecter LoginAction vous obtiendrez une instance à l'autre.

Si vous voulez un autre exemple pour chaque appel, alors vous devez appeler getBean à chaque fois d'injecter dans un singleton bean va pas le faire.

19voto

Dave Newton Points 93112

Le fait que le haricot injecté dans le contrôleur ait une portée de prototype ne signifie pas que le contrôleur l’est!

12voto

kartheek Points 155

@controller est un objet singleton, et si vous injectez un bean prototype à une classe singleton, le bean prototype sera aussi singleton, sauf si vous spécifiez à l'aide de la propriété lookup-method qui crée une nouvelle instance de bean prototype pour chaque appel que vous effectuez.

3voto

nicholas.hauschild Points 21796

Utiliser ApplicationContextAware vous lie à Spring (ce qui peut ne pas être un problème). Je recommanderais de passer un LoginActionFactory , auquel vous pouvez demander une nouvelle instance de LoginAction chaque fois que vous en avez besoin.

-12voto

flyerfang Points 49

votre contrôleur a également besoin du @Scope ("prototype") defind

comme ça:

 @Controller
@Scope("prototype")
public class HomeController { 
 .....
 .....
 .....

}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X