Je comprends qu'un bean géré fonctionne comme un contrôleur, car votre seule tâche est de "lier" la couche de vue au modèle.
Pour utiliser un bean en tant que bean géré, je dois déclarer l'annotation @ManagedBean
, Ce qui me permet de communiquer directement JSF avec le bean.
Si je veux injecter un composant (de Spring) dans ce managedBean, j'ai deux façons possibles:
Choisissez la propriété dans ManagedBean (comme "BasicDAO dao") et déclarez @ManagedProperty(#{"basicDAO"})
au-dessus de la propriété. Ce faisant, j'injecte le bean "basicDAO"
De Spring dans ManagedBean.
Déclaré @Controller dans la classe ManagedBean, alors j'aurai des annotations @ManagedBean
Et @Controller
, Tous ensemble. Et dans la propriété "BasicDAO dao"
Je dois utiliser @Autowired
De Spring.
Ma compréhension est-elle correcte?
Il existe une autre façon d'utiliser les beans gérés par Spring dans les beans gérés par JSF en étendant simplement votre bean JSF à partir de SpringBeanAutowiringSupport
et Spring 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.
}
@ManagedBean
Vs @Controller
Tout d'abord, vous devez choisir un framework pour gérer vos beans. Vous devez choisir JSF ou Spring (ou CDI) pour gérer vos beans. Bien que les travaux suivants fonctionnent, c'est fondamentalement faux:
@ManagedBean // JSF-managed.
@Controller // Spring-managed.
public class BadBean {}
Vous vous retrouvez avec deux instances complètement distinctes de la même classe de bean managé, une gérée par JSF et une autre gérée par Spring. Il n'est pas clair clairement lequel serait en fait utilisé dans EL lorsque vous le référencer comme #{someBean}
. Si vous avez le SpringBeanFacesELResolver
enregistré dans faces-config.xml
, Alors ce sera celui géré par Spring, pas celui géré par JSF. Si vous ne l'avez pas, ce serait celui géré par JSF.
De plus, lorsque vous déclarez une portée spécifique au bean géré JSF, telle que @RequestScoped
, @ViewScoped
, @SessionScoped
Ou @ApplicationScoped
À partir du package javax.faces.*
, il ne sera reconnu et utilisé que par @ManagedBean
. Il ne sera pas compris par @Controller
Car il attend sa propre annotation @Scope
. Cette valeur par défaut est singleton (portée d'application) 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 {}
Lorsque vous référencez le bean ci-dessus via #{someBean}
, Il renvoie le bean de portée d'application géré par Spring, et non le bean de portée de vue géré par JSF.
@ManagedProperty
Vs @Autowired
Le @ManagedProperty
Spécifique à JSF ne fonctionne que dans les beans gérés par JSF, c'est-à-dire lorsque vous utilisez @ManagedBean
. Le @Autowired
Spécifique à Spring ne fonctionne que dans les beans gérés par Spring, c'est-à-dire lorsque vous utilisez @Controller
. Les approches ci-dessous sont plus ou 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
Selon le javadoc ,
<application>
...
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
et ainsi vous pouvez référencer les beans gérés par Spring dans EL via #{springBeanName}
, alors vous pouvez aussi les référencer dans @ManagedProperty
, car cela définit fondamentalement le résultat évalué de l'expression EL donnée. L'inverse, l'injection d'un bean géré JSF via @Autowired
, N'est en aucun cas pris en charge. Vous pouvez cependant utiliser @Autowired
Dans un bean géré JSF lorsque vous étendez votre bean de SpringBeanAutowiringSupport
. Cela enregistrera automatiquement l'instance de bean géré JSF dans le contexte autowirable Spring lors de l'appel du constructeur, ce qui signifie que tout @Autowired
Sera disponible dans @PostConstruct
Et versions ultérieures.
@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.
}
}
Ou lorsque votre architecture ne permet pas d'étendre les beans à partir d'une classe de base différente, vous pouvez toujours enregistrer manuellement l'instance de bean géré JSF dans le contexte autoroutier Spring comme ci-dessous. Voir aussi Comment bien intégrer JSF 2 et Spring 3 (ou Spring 4) pour l'astuce.
@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
@Scope
De Spring a un support limité pour les portées JSF. Il n'y a pas d'équivalent pour @ViewScoped
De JSF. En gros, vous pouvez soit développer vos propres étendues, soit vous en tenir à enregistrer manuellement l'instance de bean géré JSF dans le contexte autoroutier de Spring, 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 la portée du flux.
Depuis Java EE 6, CDI est proposé comme alternative standard à Spring DI. Il a respectivement @Named
Et @Inject
Annotations pour cela et aussi son propre ensemble de portées . Je ne sais pas comment il interagit avec Spring car je n'utilise pas Spring, mais @Inject
Fonctionne dans un @ManagedBean
Et @ManagedProperty
Dans un @ManagedBean
peut référencer un bean @Named
. En revanche, @ManagedProperty
ne fonctionne pas dans un bean @Named
.
Le but de CDI est d'unifier tous les différents cadres de gestion de bean en une seule spécification/interface. Spring aurait pu être une implémentation CDI complète, mais ils ont choisi de ne l'implémenter que partiellement (seul JSR-330 javax.inject.*
Est pris en charge, mais JSR-299 javax.enterprise.context.*
Non). Voir aussi Spring supportera-t-il CDI? et ce tutoriel .
JSF passera à CDI pour la gestion des beans et dépréciera @ManagedBean
Et ses amis dans une future version.
@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.
}
}
Pour ce faire, le plus simple est via XML. J'ai utilisé @Component
dans un bean géré jsf déjà fait mais @Autowired
n'a pas fonctionné car le bean géré était déjà présent dans faces-config.xml. S'il est obligatoire de conserver cette définition de bean géré avec sa propriété managée dans le fichier xml, il est suggéré d'ajouter le bean spring comme autre propriété gérée à l'intérieur de la balise de bean managé. Ici, le bean de printemps est défini dans spring-config.xml (peut être câblé en alternance quelque part). veuillez vous référer https://stackoverflow.com/a/19904591/5620851
édité par moi. Je suggère de l'implémenter complètement via l'annotation @Managed et @Component ou via xml pour les deux.