Ich verstehe, dass eine verwaltete Bean wie ein Controller funktioniert, da Ihre einzige Aufgabe darin besteht, die Ansichtsebene mit dem Modell zu "verknüpfen".
Um ein Bean als verwaltetes Bean zu verwenden, muss ich die Annotation @ManagedBean
Deklarieren, damit ich JSF direkt mit dem Bean kommunizieren kann.
Wenn ich eine Komponente (von Spring) in diese managedBean einspeisen möchte, habe ich zwei Möglichkeiten:
Wählen Sie die Eigenschaft in ManagedBean (wie "BasicDAO dao") und deklarieren Sie @ManagedProperty(#{"basicDAO"})
über der Eigenschaft. Dabei injiziere ich die Bohne "basicDAO"
Von Spring in ManagedBean.
@Controller in der ManagedBean-Klasse deklariert, dann habe ich alle zusammen die Annotationen @ManagedBean
Und @Controller
. Und in der Eigenschaft "BasicDAO dao"
Muss ich @Autowired
Von Spring verwenden.
Ist mein Verständnis korrekt?
Es gibt eine andere Möglichkeit, Spring-Managed-Beans in JSF-Managed-Beans zu verwenden, indem Sie Ihre JSF-Bean einfach von SpringBeanAutowiringSupport
aus erweitern. Spring übernimmt dann die Abhängigkeitsinjektion.
@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport {
@Autowired
private SpringBeanClass springBeanName; // No setter required.
// springBeanName is now available.
}
@ManagedBean
Vs @Controller
Zunächst sollten Sie ein Framework auswählen, um Ihre Beans zu verwalten. Sie sollten entweder JSF oder Spring (oder CDI) wählen, um Ihre Beans zu verwalten. Während das Folgende funktioniert, ist es grundsätzlich falsch:
@ManagedBean // JSF-managed.
@Controller // Spring-managed.
public class BadBean {}
Sie erhalten zwei vollständig getrennte Instanzen derselben verwalteten Bean-Klasse, eine von JSF und eine von Spring. Es ist nicht direkt klar, welches tatsächlich in EL verwendet wird, wenn Sie es als #{someBean}
Bezeichnen. Wenn Sie das SpringBeanFacesELResolver
in faces-config.xml
Registriert haben, ist es das Spring-Managed, nicht das JSF-Managed. Wenn Sie das nicht haben, dann wäre es das JSF-verwaltete.
Wenn Sie einen JSF-verwalteten Bean-spezifischen Bereich wie @RequestScoped
, @ViewScoped
, @SessionScoped
Oder @ApplicationScoped
Aus dem Paket javax.faces.*
Deklarieren, es wird nur von @ManagedBean
erkannt und verwendet. Es wird von @Controller
Nicht verstanden, da es eine eigene Annotation @Scope
Erwartet. Bei Abwesenheit ist dies standardmäßig Singleton (Anwendungsbereich).
@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
@Controller // Spring-managed (without own scope, so actually becomes a singleton).
public class BadBean {}
Wenn Sie die obige Bean mit #{someBean}
Referenzieren, wird die Bean mit Spring-Managed-Anwendungsbereich zurückgegeben, nicht die Bean mit JSF-Managed-View-Bereich.
@ManagedProperty
Vs @Autowired
Das JSF-spezifische @ManagedProperty
Funktioniert nur in JSF-verwalteten Beans, d. H. Wenn Sie @ManagedBean
Verwenden. Das Spring-spezifische @Autowired
Funktioniert nur in Spring-verwalteten Beans, d. H. Wenn Sie @Controller
Verwenden. Die folgenden Ansätze sind weniger oder gleichwertiger und können nicht gemischt werden:
@ManagedBean // JSF-managed.
@RequestScoped // JSF-managed scope.
public class GoodBean {
@ManagedProperty("#{springBeanName}")
private SpringBeanClass springBeanName; // Setter required.
}
@Component // Spring-managed.
@Scope("request") // Spring-managed scope.
public class GoodBean {
@Autowired
private SpringBeanClass springBeanName; // No setter required.
}
Beachten Sie, dass, wenn Sie SpringBeanFacesELResolver
in faces-config.xml
Gemäß javadoc registriert haben,
<application>
...
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
und so können Sie Spring Managed Beans in EL über #{springBeanName}
referenzieren, dann können Sie sie auch nur in @ManagedProperty
referenzieren, da dies im Grunde das ausgewertete Ergebnis des angegebenen EL-Ausdrucks festlegt. Umgekehrt wird das Injizieren einer JSF-verwalteten Bean über @Autowired
In keiner Weise unterstützt. Sie können jedoch @Autowired
In einer JSF-verwalteten Bean verwenden, wenn Sie Ihre Bean von SpringBeanAutowiringSupport
erweitern. Dadurch wird die JSF-verwaltete Bean-Instanz während des Konstruktoraufrufs automatisch im autowünschbaren Spring-Kontext registriert, was bedeutet, dass alles @Autowired
In @PostConstruct
Und höher verfügbar ist.
@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport implements Serializable {
@Autowired
private SpringBeanClass springBeanName; // No setter required.
@PostConstruct
private void init() {
// springBeanName is now available.
}
}
Wenn Ihre Architektur das Erweitern von Beans von einer anderen Basisklasse nicht zulässt, können Sie die JSF-verwaltete Bean-Instanz wie unten beschrieben immer manuell im autowirable-Kontext von Spring registrieren. Siehe auch Wie man JSF 2 und Spring 3 (oder Spring 4) gut integriert für den Trick.
@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {
@Autowired
private SpringBeanClass springBeanName; // No setter required.
@PostConstruct
private void init() {
FacesContextUtils
.getRequiredWebApplicationContext(FacesContext.getCurrentInstance())
.getAutowireCapableBeanFactory().autowireBean(this);
// springBeanName is now available.
}
}
@XxxScoped
Vs @Scope
Spring @Scope
Unterstützt JSF-Bereiche nur eingeschränkt. Es gibt kein Äquivalent für JSFs @ViewScoped
. Grundsätzlich können Sie entweder Ihre eigenen Bereiche erstellen oder die JSF-verwaltete Bean-Instanz wie oben gezeigt manuell im automatischen Spring-Kontext registrieren.
Und von der anderen Seite an wurde Spring WebFlow in JSF 2.2 über eine neue Annotation @FlowScoped
Übernommen. Wenn Sie also bereits mit JSF 2.2 arbeiten, müssen Sie Spring WebFlow nicht unbedingt verwenden, wenn Sie nur den Flow-Bereich verwenden möchten.
Seit Java EE 6 wird CDI als Standardalternative zu Spring DI angeboten. Es verfügt über entsprechende @Named
- und @Inject
- Annotationen und einen eigenen Satz von Gültigkeitsbereichen Ich bin mir nicht sicher, wie es mit Spring interagiert, da ich Spring nicht verwende, aber @Inject
Funktioniert in einem @ManagedBean
Und @ManagedProperty
In einem @ManagedBean
kann auf eine @Named
- Bean verweisen. Andererseits funktioniert @ManagedProperty
in einer @Named
- Bean nicht.
Der Zweck von CDI besteht darin, alle verschiedenen Bean-Management-Frameworks in nur einer Spezifikation/Schnittstelle zu vereinheitlichen. Spring hätte eine vollständige CDI-Implementierung sein können, diese wurde jedoch nur teilweise implementiert (nur JSR-330 javax.inject.*
Wird unterstützt, JSR-299 javax.enterprise.context.*
Jedoch nicht). Siehe auch Wird Spring CDI unterstützen? und dieses Tutorial .
JSF wird für die Bean-Verwaltung auf CDI umsteigen und in einer zukünftigen Version @ManagedBean
Und Freunde ablehnen.
@Named // CDI-managed.
@ViewScoped // CDI-managed scope.
public class BetterBean implements Serializable {
@Inject
private SpringBeanClass springBeanName; // No setter required.
@PostConstruct
private void init() {
// springBeanName is now available.
}
}
Der einfache Weg dazu führt über XML. Ich benutzte @Component
in bereits gemachtem jsf managed bean aber @Autowired
hat nicht funktioniert, da die verwaltete Bean bereits in der Datei faces-config.xml vorhanden war. Wenn diese verwaltete Bean-Definition zusammen mit ihrer verwalteten Eigenschaft in der XML-Datei unbedingt beibehalten werden muss, wird empfohlen, die Spring Bean als weitere verwaltete Eigenschaft im Tag der verwalteten Bean hinzuzufügen. Hier wird die Spring Bean in der Datei spring-config.xml definiert (kann alternativ auch automatisch verdrahtet werden). Bitte beziehen Sie sich auf https://stackoverflow.com/a/19904591/5620851
bearbeitet von mir. Ich empfehle, es entweder durch Annotation @Managed und @Component oder durch XML für beide zu implementieren.