Introduction

Ce tutoriel montre les différents scopes que vous pouvez attribuer à un Bean ou à un Component dans Spring Framework.

Il est important de comprendre qu’une définition de Bean est juste une recette pour créer des instances d’une classe en suivant la définition de cette recette. Cette recette peut ensuite être utilisée une ou plusieurs fois au cours du cycle de vie de l’application pour créer une instance du Bean.

Le Bean scope est l’une des principales caractéristiques de la configuration du Bean dans Spring. Le scope va indiquer quand et comment l’objet de la définition du Bean va être instancié.

Spring inclut 7 scopes Bean différents :

  • Singleton
  • Prototype
  • Request
  • Session
  • Session globale
  • Application
  • Websocket

Parmi ceux-ci, seuls 5 sont disponibles dans une application web-aware.

Singleton

Singleton est le scope par défaut pour un Bean, celui qui sera utilisé si rien d’autre n’est indiqué. Cette portée implique que le conteneur Spring créera une instance uniquement partagée de la classe désignée par ce Bean, ainsi à chaque fois que le Bean sera requis, le même objet sera injecté. L’instance de ce Bean est stockée dans un cache géré par Spring.

On peut utiliser des annotations pour définir des singletons comme dans l’exemple suivant :

Comme déjà indiqué, Singleton est le scope par défaut d’un Spring Bean, il n’est donc pas nécessaire de définir son @Scope (premier exemple). Cependant, pour une meilleure clarté et compréhension, vous pouvez mettre ce fait en évidence en utilisant l’annotation @Scope comme dans le deuxième exemple.

Le test suivant montre le comportement d’un singleton:

Le comportement pour les classes annotées @Component (ou n’importe laquelle de ses extensions) est le même que pour les Beans ordinaires, elles seront singleton à moins d’être configurées différemment.

Par exemple, un @RestController comme le suivant:

Assert le test suivant:

Prototype

Dans la portée Prototype, le conteneur Spring créera une nouvelle instance de l’objet décrit par le bean chaque fois qu’il recevra une requête. L’une des règles de base énoncées dans la documentation de Spring est d’utiliser des beans scopés Prototype lorsqu’on travaille sur un environnement où il y a une gestion de session (Stateful) et d’utiliser le scope Singleton lorsqu’on travaille sur des environnements sans gestion de session (Stateless), cependant il existe bien d’autres cas d’utilisation plus nombreux et différents.

Il est important de souligner que le conteneur Spring ne prend pas la responsabilité de ce qui arrive aux instances des objets reçus lors de la requête d’un bean. Cela signifie que c’est au développeur d’effectuer le nettoyage et de libérer les ressources référencées par l’objet défini par le Bean.

De même que pour le scope Singleton, nous pouvons définir un bean avec le scope Prototype en utilisant les annotations comme suit : :

.

1
2
3
4
5

.

@Bean(name = PROTOTYPE_BEAN_SAMPLE_NAME)
@Scope(SCOPE_PROTOTYPE)
public SamplePrototype() {
return new Sample() ;
}

Le test suivant montre le comportement d’un prototype :

Singleton Beans avec Prototype Beans injectés

Il est très important de souligner que lorsque vous définissez un Singleton Bean avec des dépendances ou des Prototype Beans encapsulés, l’injection se produit lorsque l’objet Singleton est instancié donc l’injection ne se produit qu’une fois. Ainsi, l’objet injecté défini par le Prototype Bean sera toujours la même instance même s’il a été défini avec une portée Prototype.

Par exemple, nous pouvons définir une classe avec un Bean injecté comme suit :

Nous définissons les Beans suivants :

Le premier Bean (Sample) a une portée Prototype et sera injecté dans le second (SampleAutowired) qui a une portée Singleton. Comme expliqué dans les paragraphes précédents, le comportement attendu est que chaque fois que nous demandons un SampleAutowired, l’instance de Sample sera la même même même si elle a un Prototype scope car elle a été instanciée et assignée une seule fois lorsque SampleAutowired (Singleton) a été instancié pour la première fois….

Cela est prouvé dans le test suivant:

Scope d’application web-aware

Comme mentionné dans l’introduction, le reste des scopes ne sont disponibles que pour les applications web-aware.

Request

Le conteneur Spring créera une nouvelle instance de l’objet défini par le Bean chaque fois qu’il recevra une requête HTTP.

Pour définir un Bean avec cette portée, nous pouvons utiliser les annotations suivantes selon qu’il s’agit d’un Bean ou d’un Component:

Le comportement pour le @RestController dans le snippet précédent peut être testé comme suit :

Session

Le conteneur Spring créera une nouvelle instance de l’objet défini par le Bean pour chacune des sessions HTTP (application Stateful) et retournera cette même instance chaque fois qu’il recevra une requête au sein de la même session.

Le comportement pour le @RestController dans le snippet précédent peut être testé comme suit :

Session globale

Le scope Global Session a un comportement similaire au scope Session mais il n’est applicable que dans le contexte des applications web basées sur les Portlets. La spécification Portlet définit une session globale comme une session qui est partagée entre tous les Portlets qui composent une application.

Si ce scope est utilisé dans une application web ordinaire, le comportement des Beans définis avec ce scope sera le même que s’ils avaient été définis avec un scope Session.

Application

Le scope Application a un comportement très similaire au scope Singleton, Spring créera une nouvelle instance fo le bean pour chaque ServletContext. Une application Spring peut avoir plusieurs ServletContext, ainsi l’instance retournée par Spring pour chaque requête du Bean sera la même au sein d’un même contexte, mais différente pour chacun des contextes.

Websocket

Le conteneur Spring créera une nouvelle instance de l’objet défini par le Bean et retournera cette instance pour chaque requête produite au sein du cycle de vie d’un Websocket.

Conclusion

Catégories : Articles

0 commentaire

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *