Ich möchte eine kommentierte Prototyp-Bean in meinem Controller verwenden. Aber der Frühling schafft stattdessen eine Singleton-Bohne. Hier ist der Code dafür:
@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-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;
}
}
Geschwindigkeitsvorlage:
LoginAction counter: ${loginAction.str}
In Spring config.xml
ist das Scannen von Komponenten aktiviert:
<context:annotation-config />
<context:component-scan base-package="com.springheat" />
<mvc:annotation-driven />
Ich erhalte jedes Mal eine erhöhte Anzahl. Ich kann nicht herausfinden, wo ich falsch liege!
Aktualisieren
Wie von @gkamal vorgeschlagen , habe ich darauf aufmerksam gemacht HomeController
webApplicationContext
und das Problem gelöst.
aktualisierter 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", getLoginAction());
return mav;
}
public LoginAction getLoginAction() {
return (LoginAction) context.getBean("loginAction");
}
}
spring
spring-mvc
Tim und Struppi
quelle
quelle
Antworten:
Der Scope-Prototyp bedeutet, dass jedes Mal, wenn Sie spring (getBean oder Abhängigkeitsinjektion) nach einer Instanz fragen, eine neue Instanz erstellt und ein Verweis darauf angegeben wird.
In Ihrem Beispiel wird eine neue Instanz von LoginAction erstellt und in Ihren HomeController eingefügt. Wenn Sie einen anderen Controller haben, in den Sie LoginAction injizieren, erhalten Sie eine andere Instanz.
Wenn Sie für jeden Aufruf eine andere Instanz wünschen - dann müssen Sie jedes Mal getBean aufrufen -, wird dies durch Injizieren in eine Singleton-Bean nicht erreicht.
quelle
request
Gültigkeitsbereich anstelle einesprototype
Gültigkeitsbereichs gehabt hätte ? Müssen Sie die Bohne noch mit abrufencontext.getBean(..)
?Seit Spring 2.5 gibt es einen sehr einfachen (und eleganten) Weg, dies zu erreichen.
Sie können einfach die Parameter
proxyMode
undvalue
die@Scope
Anmerkung ändern .Mit diesem Trick können Sie vermeiden, jedes Mal, wenn Sie einen Prototyp in eine Singleton-Bean benötigen, zusätzlichen Code zu schreiben oder den ApplicationContext einzufügen.
Beispiel:
Mit der obigen Konfiguration
LoginAction
(innenHomeController
) ist immer ein Prototyp , obwohl der Controller ein Singleton ist .quelle
Nur weil die in den Controller eingespritzte Bohne prototypisch ist, heißt das nicht, dass der Controller dies ist!
quelle
@controller ist ein Singleton-Objekt. Wenn Sie eine Prototyp-Bean in eine Singleton-Klasse einfügen, wird die Prototyp-Bean auch als Singleton erstellt, es sei denn, Sie geben die Eigenschaft lookup-method an, mit der für jeden Aufruf eine neue Instanz der Prototyp-Bean erstellt wird.
quelle
Wie von nicholas.hauschild erwähnt, ist es keine gute Idee, den Frühlingskontext zu injizieren. In Ihrem Fall reicht @Scope ("Anfrage") aus, um das Problem zu beheben. Angenommen, Sie benötigen mehrere Instanzen der
LoginAction
Controller-Methode. In diesem Fall würde ich empfehlen, die Bean of Supplier ( Spring 4- Lösung) zu erstellen :Dann injizieren Sie es in die Steuerung:
quelle
ObjectFactory
die dem gleichen Zweck wie der Lieferant dienen, aber als normal definiert werden können,@Bean
womit ich meine, dass kein Lambda zurückgegeben werden muss.Die Verwendung
ApplicationContextAware
bindet Sie an Spring (was ein Problem sein kann oder nicht). Ich würde empfehlen, ein zu übergebenLoginActionFactory
, das SieLoginAction
jedes Mal, wenn Sie eines benötigen , nach einer neuen Instanz von a fragen können .quelle
factory-method
hier ...LoginActionFactory
in den Controller,factory-method
scheint aber das Problem nicht zu lösen, da nur eine weitere Spring Bean über die Fabrik erstellt wird. Durch Injizieren dieser Bean in den Singleton-Controller wird das Problem nicht behoben.Verwenden Sie den Anforderungsbereich
@Scope("request")
, um Bean für jede Anforderung oder@Scope("session")
Bean für jeden Sitzungsbenutzer abzurufen.quelle
Eine Protoype-Bohne, die in eine Singelton-Bohne injiziert wird, verhält sich wie Singelton, bis sie ausdrücklich dazu aufgefordert wird, eine neue Instanz von get bean zu erstellen.
quelle
@Komponente
@Scope (Wert = "Prototyp")
TennisCoach der öffentlichen Klasse implementiert Coach {
// etwas Code
}}
quelle
Sie können eine statische Klasse in Ihrem Controller wie folgt erstellen:
quelle
Eine andere Möglichkeit, das Problem zu lösen, ist die Methodeninjektion mit der Annotation @Lookup .
Hier ist ein schöner Artikel zu diesem Problem des Injizierens von Prototyp-Beans in eine Singleton-Instanz mit mehreren Lösungen.
https://www.baeldung.com/spring-inject-prototype-bean-into-singleton
quelle
Ihr Controller benötigt auch die
@Scope("prototype")
definiertenso was:
quelle