Tout d'abord, permettez-moi de faire quelques éclaircissements:
Définition du bean géré : généralement un bean géré est un objet dont son cycle de vie (construction, destruction, etc.) est géré par un conteneur.
Dans Java ee, nous avons de nombreux conteneurs qui gèrent le cycle de vie de leurs objets, comme le conteneur JSF, le conteneur EJB, le conteneur CDI, le conteneur Servlet, etc.
Tous ces conteneurs fonctionnent de manière indépendante, ils démarrent lors de l'initialisation du serveur d'applications et analysent les classes de tous les artefacts, y compris les fichiers jar, ejb-jar, war et ear au moment du déploiement, et collectent et stockent des métadonnées à leur sujet, puis lorsque vous avez besoin d'un objet d'une classe au moment de l'exécution, ils vous donneront des instances de ces classes et après avoir terminé le travail, ils les détruiront.
Nous pouvons donc dire que nous avons:
- Beans gérés JSF
- Beans gérés par CDI
- Beans gérés par EJB
- Et même les servlets sont des beans gérés car ils sont instanciés et détruits par un conteneur, qui est un conteneur de servlet.
Ainsi, lorsque vous voyez le mot Managed Bean, vous devez vous renseigner sur le contexte ou le type de celui-ci (JSF, CDI, EJB, etc.)
Ensuite, vous pourriez vous demander pourquoi nous avons beaucoup de ces conteneurs: AFAIK, les gars de Java EE voulaient avoir un cadre d'injection de dépendances, mais ils ne pouvaient pas rassembler toutes les exigences dans une spécification car ils ne pouvaient pas prédire les exigences futures et ils ont créé EJB 1.0 et ensuite 2.0 puis 3.0 et maintenant 3.1 mais la cible d'EJB était juste pour certaines exigences (transaction, modèle de composant distribué, etc.).
En même temps (en parallèle), ils ont réalisé qu'ils devaient également prendre en charge JSF, puis ils ont créé des beans gérés par JSF et un autre conteneur pour les beans JSF et ils l'ont considéré comme un conteneur DI mature, mais ce n'était toujours pas un conteneur complet et mature.
Après cela, Gavin King et d'autres gentils gars;) ont créé CDI qui est le conteneur DI le plus mature que j'ai vu. CDI (inspiré de Seam2, Guice et Spring) a été conçu pour combler le vide entre JSF et EJB et beaucoup d'autres choses utiles comme l'injection de pojo, les méthodes de production, les intercepteurs, les décorateurs, l'intégration SPI, très flexible, etc. et cela peut même le faire. ce que font les beans gérés EJB et JSF, nous ne pouvons alors avoir qu'un seul conteneur DI mature et puissant. Mais pour des raisons de rétrocompatibilité et des raisons politiques, les gars de Java EE veulent les conserver !!!
Vous trouverez ici la différence et les cas d'utilisation pour chacun de ces types:
Beans gérés JSF, Beans CDI et EJB
JSF a été initialement développé avec son propre mécanisme d'injection de bean géré et de dépendances qui a été amélioré pour JSF 2.0 pour inclure des beans basés sur des annotations. Lorsque CDI a été publié avec Java EE 6, il était considéré comme le framework de bean géré pour cette plate-forme et, bien sûr, les EJB les dépassaient tous depuis plus d'une décennie.
Le problème est bien sûr de savoir lequel utiliser et quand les utiliser.
Commençons par les beans gérés JSF les plus simples.
Beans gérés JSF
En bref, ne les utilisez pas si vous développez pour Java EE 6 et utilisez CDI. Ils fournissent un mécanisme simple pour l'injection de dépendances et la définition de beans de sauvegarde pour les pages Web, mais ils sont beaucoup moins puissants que les beans CDI.
Ils peuvent être définis à l'aide de l' @javax.faces.bean.ManagedBean
annotation qui prend un paramètre de nom facultatif. Ce nom peut être utilisé pour référencer le bean à partir des pages JSF.
L'étendue peut être appliquée au bean en utilisant l'une des différentes étendues définies dans le javax.faces.bean
package qui incluent la demande, la session, l'application, la vue et les étendues personnalisées.
@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
....
....
}
Les beans JSF ne peuvent pas être mélangés avec d'autres types de beans sans une sorte de codage manuel.
Haricots CDI
CDI est le cadre de gestion de bean et d'injection de dépendances qui a été publié dans le cadre de Java EE 6 et il comprend une fonction de bean géré complète et complète. Les beans CDI sont bien plus avancés et flexibles que de simples beans gérés JSF. Ils peuvent utiliser les intercepteurs, la portée de la conversation, les événements, l'injection sécurisée de type, les décorateurs, les stéréotypes et les méthodes de production.
Pour déployer des beans CDI, vous devez placer un fichier appelé beans.xml dans un dossier META-INF sur le chemin de classe. Une fois que vous faites cela, chaque bean du package devient un bean CDI. Il y a beaucoup de fonctionnalités dans CDI, trop nombreuses pour être couvertes ici, mais comme référence rapide pour les fonctionnalités de type JSF, vous pouvez définir la portée du bean CDI en utilisant l'une des portées définies dans le javax.enterprise.context
package (à savoir, demande, conversation , les portées de session et d'application). Si vous souhaitez utiliser le bean CDI à partir d'une page JSF, vous pouvez lui donner un nom à l'aide de l' javax.inject.Named
annotation. Pour injecter un bean dans un autre bean, vous annotez le champ avec une javax.inject.Inject
annotation.
@Named("someBean")
@RequestScoped
public class SomeBean {
@Inject
private SomeService someService;
}
L'injection automatique comme celle définie ci-dessus peut être contrôlée grâce à l'utilisation de qualificatifs qui peuvent aider à faire correspondre la classe spécifique que vous souhaitez injecter. Si vous disposez de plusieurs types de paiement, vous pouvez ajouter un qualificatif indiquant s'il est asynchrone ou non. Bien que vous puissiez utiliser l' @Named
annotation comme qualificatif, vous ne devriez pas le faire car il est fourni pour exposer les beans en EL.
CDI gère l'injection de beans avec des portées incompatibles grâce à l'utilisation de proxies. Pour cette raison, vous pouvez injecter un bean de portée de requête dans un bean de portée de session et la référence sera toujours valide sur chaque requête car pour chaque requête, le proxy se reconnecte à une instance active du bean de portée de requête.
CDI prend également en charge les intercepteurs, les événements, la nouvelle portée de conversation et de nombreuses autres fonctionnalités, ce qui en fait un bien meilleur choix par rapport aux beans gérés JSF.
EJB
Les EJB sont antérieurs aux beans CDI et sont en quelque sorte similaires aux beans CDI et très différents à d'autres égards. Principalement, la différence entre les beans CDI et les EJB est que les EJB sont:
- Transactionnel
- À distance ou local
- Capable de passiver les beans avec état en libérant des ressources
- Capable d'utiliser des minuteries
- Peut être asynchrone
Les deux types d'EJB sont appelés sans état et avec état. Les EJB sans état peuvent être considérés comme des beans à usage unique thread-safe qui ne maintiennent aucun état entre deux requêtes Web. Les EJB avec état conservent l'état et peuvent être créés et rester en place aussi longtemps que nécessaire jusqu'à ce qu'ils soient éliminés.
La définition d'un EJB est simple, il vous suffit d'ajouter une javax.ejb.Stateless
ou une javax.ejb.Stateful
annotation à la classe.
@Stateless
public class BookingService {
public String makeReservation(Item Item, Customer customer) {
...
...
}
}
Les beans sans état doivent avoir une portée dépendante tandis qu'un bean session avec état peut avoir n'importe quelle portée. Par défaut, ils sont transactionnels, mais vous pouvez utiliser l'annotation d'attribut de transaction.
Alors que les EJB et les beans CDI sont très différents en termes de fonctionnalités, l'écriture du code pour les intégrer est très similaire puisque les beans CDI peuvent être injectés dans les EJB et les EJB peuvent être injectés dans les beans CDI. Il n'est pas nécessaire de faire de distinction lors de l'injection de l'un dans l'autre. Encore une fois, les différentes portées sont gérées par CDI via l'utilisation de proxy. Une exception à cela est que CDI ne prend pas en charge l'injection d'EJB distants, mais cela peut être implémenté en écrivant une méthode de producteur simple pour cela.
L' javax.inject.Named
annotation ainsi que tous les qualificatifs peuvent être utilisés sur un EJB pour le faire correspondre à un point d'injection.
Quand utiliser quel haricot
Comment savoir quand utiliser quel grain? Facile.
N'utilisez jamais de beans gérés JSF à moins que vous ne travailliez dans un conteneur de servlet et que vous ne vouliez pas essayer de faire fonctionner CDI dans Tomcat (bien qu'il existe des archétypes Maven pour cela, il n'y a donc aucune excuse).
En général, vous devez utiliser des beans CDI, sauf si vous avez besoin des fonctionnalités avancées disponibles dans les EJB, telles que les fonctions transactionnelles. Vous pouvez écrire votre propre intercepteur pour rendre les beans CDI transactionnels, mais pour l'instant, il est plus simple d'utiliser un EJB jusqu'à ce que CDI obtienne des beans CDI transactionnels, ce qui est juste au coin de la rue. Si vous êtes coincé dans un conteneur de servlet et que vous utilisez CDI, les transactions écrites à la main ou votre propre intercepteur de transactions sont la seule option sans EJB.
Si vous devez utiliser @ViewScoped
CDI, vous devez
- utilisez le module Seam -faces ou MyFaces CODI . ajoutez simplement l'un d'entre eux à votre chemin de classe et
@ViewScoped
fonctionnera dans CDI. MyFaces CODI a un support encore plus solide de @ViewScoped
- utilisez MyFaces CODI
@ViewAccessScoped
, c'est une extension écrite sur CDI par Apache, téléchargez-la simplement et utilisez l' @ViewAccessScoped
annotation au lieu de @ViewScoped
.
- Utilisez CDI
@ConversationScoped
et rendez-le long. Voir ici pour plus d'informations .
- Utiliser l' annotation Omnifaces @ViewScoped
Certaines pièces ont été volées d' ici .