Intégration JSF de printemps: comment injecter un composant/service de printemps dans le bean géré par JSF?

je comprends qu'un bean managé fonctionne comme un contrôleur, parce que votre seule tâche est" lier " la couche de vue avec le modèle.

pour utiliser un haricot comme un haricot géré je dois déclarer @ManagedBean annotation, faisant que je peux communiquer JSF avec haricot directement.

si je veux injecter un composant (à partir du printemps) dans ce canal managé, j'ai deux possibilités:

  1. choisir la propriété dans ManagedBean (comme "BasicDAO dao") et déclarer @ManagedProperty(#{"basicDAO"}) au-dessus de la propriété. En le faisant, j'injecte le haricot "basicDAO" de Spring dans ManagedBean.

  2. a déclaré @Controller dans la classe ManagedBean, alors j'aurai @ManagedBean et @Controller annotations, toutes ensemble. Et dans la propriété "BasicDAO dao" je dois utiliser @Autowired de printemps.

est-ce que ma compréhension est correcte?

30
demandé sur BalusC 2013-08-22 22:18:12

3 réponses

il y a une autre façon d'utiliser les fèves gérées au printemps dans les fèves gérées par JSF en prolongeant simplement votre fève JSF de SpringBeanAutowiringSupport et le printemps gérera l'injection de dépendance.

@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport {

    @Autowired
    private SpringBeanClass springBeanName; // No setter required.

    // springBeanName is now available.
}
3
répondu tylerdurden 2017-11-30 22:15:50

@ManagedBean vs @Controller

tout d'abord, vous devez choisir un cadre pour gérer vos haricots. Vous devez choisir JSF ou Spring (ou CDI) pour gérer vos haricots. Alors que les travaux suivants, il est fondamentalement faux:

@ManagedBean // JSF-managed.
@Controller // Spring-managed.
public class BadBean {}

vous vous retrouvez avec deux deux instances complètement distinctes de la même classe de haricots gérés, l'une gérée par JSF et l'autre gérée d'ici le Printemps. Il n'est pas évident de savoir lequel des deux en fait serait utilisé dans EL lorsque vous le mentionnez comme #{someBean} . Si vous avez le SpringBeanFacesELResolver enregistré dans faces-config.xml , alors ce serait le ressort-géré, pas le JSF-géré. Si vous ne l'avez pas, ce sera celui géré par le JSF.

aussi, lorsque vous déclarez un champ d'application spécifique géré par JSF, tel que @RequestScoped , @ViewScoped , @SessionScoped ou @ApplicationScoped du paquet javax.faces.* , il ne sera reconnu et utilisé que par @ManagedBean . Il ne sera pas compris par @Controller comme il attend sa propre annotation @Scope . Ceci vaut par défaut pour singleton (application scope) en cas d'absence.

@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
@Controller // Spring-managed (without own scope, so actually becomes a singleton).
public class BadBean {}

quand vous faites référence à la fève ci-dessus via #{someBean} , il retournerait l'application gérée au printemps scoped bean, pas le JSF-managed view scoped bean.


@ManagedProperty vs @Autowired

le @ManagedProperty spécifique au JSF ne fonctionne que pour les haricots gérés par le JSF, c'est-à-dire lorsque vous utilisez @ManagedBean . Le @Autowired spécifique au printemps ne fonctionne que pour les haricots à gestion printanière, c'est-à-dire lorsqu'on utilise le @Controller . Les approches ci-dessous sont de moins en moins équivalentes et ne peuvent pas être mélangées:

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

notez que lorsque vous avez le SpringBeanFacesELResolver enregistré dans faces-config.xml que par le javadoc ,

<application>
    ...
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>

et ainsi vous pouvez faire référence à des haricots avec gestion de printemps dans EL via #{springBeanName} , alors vous pouvez simplement les faire référence dans @ManagedProperty aussi, car il fixe fondamentalement le résultat évalué de L'expression donnée EL. Dans l'autre sens, injecter une fève gérée par JSF via @Autowired , n'est en aucun cas supporté. Vous pouvez cependant utiliser @Autowired dans une FJB gérée lorsque vous enregistrez manuellement le JSF instance bean gérée au printemps contexte autowinable comme ci-dessous. Voir aussi comment intégrer JSF 2 et Spring 3 (ou Spring 4) bien pour le truc.

@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

Printemps @Scope a un support limité pour le JSF étendues. Il n'y a pas d'équivalent pour le @ViewScoped de JSF . En gros, soit tu ramènes tes propres lunettes, soit tu t'en tiens à l'enregistrement manuel. le JSF a géré l'instance bean au printemps dans un contexte autowinable comme indiqué ci-dessus.

et, de l'autre côté, Spring WebFlow a été repris dans JSF 2.2 via une nouvelle annotation @FlowScoped . Donc, si vous êtes déjà sur JSF 2.2, vous n'avez pas nécessairement besoin d'utiliser Spring WebFlow si vous voulez uniquement le débitmètre.


CDI - essayer d'unifier tous les

depuis Java EE 6, le CDI est proposé comme alternative standard au Spring DI. Il a respectivement @Named et @Inject annotations pour ceci et aussi son propre ensemble de portées. Je ne sais pas comment il interagit avec le printemps car je n'utilise pas le printemps, mais @Inject fonctionne à l'intérieur d'un @ManagedBean , et @ManagedProperty à l'intérieur d'un @ManagedBean peut faire référence à un @Named haricot. D'autre part, @ManagedProperty ne fonctionne pas à l'intérieur d'un @Named bean.

L'Objectif du CDI est d'unifier toutes les fèves différentes cadres de gestion en une seule spécification/interface. Le printemps aurait pu être une mise en œuvre complète du CDI, mais ils ont choisi de ne l'appliquer que partiellement (seul le JSR-330 javax.inject.* est soutenu, mais pas le JSR-299 javax.enterprise.context.* ). Voir aussi Printemps de soutien CDI? et ce tutoriel .

JSF sera transféré au CDI pour la gestion des haricots et déprécier @ManagedBean et amis dans une version future.

voir aussi:

69
répondu BalusC 2017-05-23 12:10:44

la façon la plus simple de le faire est par XML. J'ai utilisé @Component dans déjà fait JSF géré bean mais @Autowired n'a pas fonctionné parce que géré bean était déjà là dans les visages-config.XML. S'il est obligatoire de conserver cette définition de fève gérée avec sa propriété gérée dans le fichier xml, alors il est suggéré d'ajouter la fève de printemps comme une autre propriété gérée à l'intérieur de l'étiquette de fève gérée. Ici le haricot de printemps est là défini dans la config de printemps.xml(peut être autowired somewhere alternativement.) veuillez vous référer https://stackoverflow.com/a/19904591/5620851

édité par moi. Je suggère soit de le mettre en œuvre tout à fait par annotation @Managed et @Component ou via xml pour les deux.

1
répondu hi.nitish 2017-05-23 12:18:25