web-dev-qa-db-de.com

Spring-JSF-Integration: Wie wird eine Spring-Komponente / ein Spring-Service in ein JSF-verwaltetes Bean eingefügt?

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:

  1. 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.

  2. @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?

39

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.
}
8
tylerdurden

@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.


CDI - versucht alles zu vereinheitlichen

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.
    }
}

Siehe auch:

77
BalusC

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.

1
hi.nitish