Projets
Pages enfant
  • 1.7 Les beans Spring

Comparaison des versions

Légende

  • Ces lignes ont été ajoutées. Ce mot a été ajouté.
  • Ces lignes ont été supprimées. Ce mot a été supprimé.
  • La mise en forme a été modifiée.
Commentaire: Migrated to Confluence 5.3
Astuce
titleRelu

Relecture RB faite le

Balise Wiki
{tip:title=Relu}Relecture RB faite le

16/02/2011

{tip}

Ce

...

chapitre

...

n'a

...

pas

...

la

...

prétention

...

d'être

...

une

...

formation

...

à

...

Spring

...

.

...

Pour

...

plus

...

d'informations,

...

vous

...

pouvez

...

vous

...

reporter

...

à

...

la

...

documentation

...

de springsource ( HTML / PDF ). Ne sont abordés ici que quelques détails permettant de mieux comprendre certains éléments des fichiers de configuration de esup-commons.

Remarque

Esup-commons V2 utilise Spring 3

Tout au long de ce chapitre nous allons nous appuyer sur un exemple (configuration du gestionnaire d'exceptions) :

Bloc de code
 [springsource|http://www.springsource.org/] ( [HTML|http://static.springsource.org/spring/docs/3.1.0.M1/spring-framework-reference/html] / [PDF|http://static.springsource.org/spring/docs/3.1.0.M1/spring-framework-reference/pdf/spring-framework-reference.pdf] ). Ne sont abordés ici que quelques détails permettant de mieux comprendre certains éléments des fichiers de configuration de _esup-commons_.

{note}{_}Esup-commons V2_ utilise Spring 3{note}

Tout au long de ce chapitre nous allons nous appuyer sur un exemple (configuration du gestionnaire d'exceptions) :
\\
{code}
<bean id="exceptionServiceFactory"
      class="org.esupportail.commons.services.exceptionHandling.CachingEmailExceptionServiceFactoryImpl"
      parent="abstractApplicationAwareBean">
   <property name="smtpService" ref="smtpService" />
   <property name="recipientEmail" value="${exceptionHandling.email}" />
   <property name="exceptionViews">
      <map>
         <entry key="java.lang.Exception" value="go_exception" />
      </map>
   </property>
   <property name="logLevel" value="${exceptionHandling.logLevel}" />
   <property name="cacheManager" ref="cacheManager" />
   <property name="cacheName" value="" />
</bean>
{code}
----
h4. Sommaire :
{toc:maxLevel=3}
----
h2. Les fichiers de configuration

_Spring_ permet de créer des objets (appelés alors _beans_) en les déclarant dans un fichier de configuration _XML_.

Le fichier de configuration principal (*

...

Sommaire :

Sommaire
maxLevel3

...

Les fichiers de configuration

Spring permet de créer des objets (appelés alors beans) en les déclarant dans un fichier de configuration XML.

Le fichier de configuration principal (properties/applicationContext.xml

...

)

...

est

...

déclaré

...

dans

...

le

...

*web.xml

...

*

...

sous

...

la

...

forme

...

d'un

...

paramètre

...

de

...

l'application

...

:

{
Bloc de code
}
<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:/properties/applicationContext.xml</param-value>
</context-param>
{code}

Dans _

Dans esup-commons

...

ce

...

fichier

...

de

...

configuration

...

principal

...

contient

...

seulement

...

des

...

inclusions

...

de

...

fichiers

...

de

...

configuration

...

spécialisés

...

par

...

domaine,

...

comme

...

par

...

exemple:

{
Bloc de code
}
<import resource="exceptionHandling/exceptionHandling.xml" />
{code}

Il

...

est

...

possible,

...

suivant

...

les

...

besoins

...

de

...

votre

...

application,

...

de

...

supprimer

...

ou

...

d'ajouter

...

des

...

fichiers

...

de

...

configuration

...

spécialisés.

...

L'injection

...

de

...

données

...

Une

...

des

...

caractéristiques

...

de

...

base

...

de

...

Spring

...

est

...

de

...

permettre

...

l'injection

...

de

...

données.

{
Remarque
}

Cette

fonctionnalité

est

aussi

possible

avec

_

JSF

_

,

qui

est

également

utilisé

dans

_

esup-commons

_

,

mais

_

JSF

_

est

moins

puissant

que

_

Spring

_

dans

ce

domaine.

_

esup-commons

_

n'utilise

donc

pas

l'injection

de

données

de

_

JSF

_

.

{note}

L'injection

...

de

...

données

...

permet

...

de

...

renseigner

...

des

...

attributs

...

d'un

...

bean

...

via

...

un

...

fichier

...

de

...

configuration.

...

Le

...

bean

...

doit

...

disposer

...

d'un

...

setter

...

pour

...

l'accès

...

à

...

ces

...

attributs.

...

Voyons

...

quelques

...

exemples...

...

Injection

...

d'une

...

chaîne

...

de

...

caractères

{
Bloc de code
}
<property name="recipientEmail" value="webmaster@domain.edu"/>
{code}

Dans

...

ce

...

cas,

...

la

...

méthode

...

setRecipentEmail()

...

sera

...

appelée

...

avec

...

pour

...

paramètre,

...

la

...

valeur

...

webmaster@domain.edu

...

.

...

Injection

...

d'un

...

autre

...

bean

{
Bloc de code
}
<property name="authenticationService" ref="authenticationService"/>
{code}

On

...

voit

...

ici

...

un

...

autre

...

aspect

...

important

...

de

...

Spring

...

qui

...

est

...

l'utilisation

...

quasi

...

systématique

...

des

...

interfaces.

...

La

...

classe

...

CachingEmailExceptionServiceFactoryImpl

...

(qui

...

correspond

...

au

...

bean

...

exceptionServiceFactory

...

et

...

contient

...

la

...

définition

...

de

...

cette

...

propriété

...

authenticationService

...

)

...

a

...

un

...

attribut

...

authenticationService

...

de

...

type

...

AuthenticationService

...

.

...

AuthenticationService

...

est

...

une

...

interface.

...

Le

...

bean

...

authenticationService

...

doit

...

donc

...

être

...

d'une

...

classe

...

qui

...

implémente

...

cette

...

interface.

...

Ceci

...

permet

...

d'avoir

...

plusieurs

...

implémentations

...

possibles

...

pour

...

cette

...

interface

...

et

...

de

...

choisir,

...

simplement

...

en

...

modifiant

...

un

...

fichier

...

de

...

configuration,

...

laquelle

...

on

...

utilise.

...

Cette

...

approche

...

est

...

particulièrement

...

intéressante

...

:

...

elle

...

permet,

...

par

...

exemple,

...

de

...

très

...

facilement

...

tester

...

une

...

couche

...

de

...

l'application

...

en

...

branchant

...

des

...

implémentations

...

de

...

tests

...

des

...

autres

...

couches

...

avec

...

lesquelles

...

le

...

bean

...

doit

...

interagir.

...

Injection

...

d'une

...

map

{
Bloc de code
}
<property name="exceptionViews">
  <map>
    <entry key="java.lang.Exception" value="go_exception" />
  </map>
</property>
{code}

h3. Injection 

Injection d'une

...

liste

{
Bloc de code
}
<property name="servers">
  <list>
    <ref bean="smtpServer1" />
    <ref bean="smtpServer2" />
  </list>
</property>
{code}

h2. Utilisation de paramètres

Afin de centraliser la configuration, une bonne pratique consiste à utiliser un fichier de configuration regroupant les paramètres de 

Utilisation de paramètres

Afin de centraliser la configuration, une bonne pratique consiste à utiliser un fichier de configuration regroupant les paramètres de l'application.

...

Ceci

...

évite

...

notamment

...

de

...

devoir

...

modifier

...

n

...

fichiers

...

différents.

...

Exemple

...

d'utilisation

...

:

{
Bloc de code
}
<property name="recipientEmail" value="${exceptionHandling.email}" />
{code}

Ici

...

la

...

propriété

...

recipientEmail

...

contiendra

...

la

...

valeur

...

contenue

...

dans

...

le

...

paramètre

...

exceptionHandling.email

...

.

...

Le

...

paramètre

...

exceptionHandling.email

...

est

...

défini

...

dans

...

le

...

fichier

...

default.properties

...

et

...

peut

...

être

...

surchargé

...

dans

...

le

...

fichier

...

config.properties

...

:

{
Bloc de code
}
exceptionHandling.email=bugs@domain.edu
{code}
{note}

Ce mécanisme est rendu possible par la définition 
Remarque

Ce mécanisme est rendu possible par la définition d'un

bean

utilisant

la

classe

_

PropertyPlaceholderConfigurer

_

de

Spring

dans

le

fichier

*

properties/applicationContext.xml

* {code}

Bloc de code

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="locations">
    <list>
      <value>classpath:/properties/defaults.properties</value>
      <value>classpath:/properties/config.properties</value>
      <value>file:${application.config.location}</value>
    </list>
  </property>
  <property name="ignoreResourceNotFound" value="true" />
</bean>
{code}

Ici

on

définit

les

propriétés

dans

le

fichier

*

defaults.properties

*

.Elles

sont

éventuellement

écrasées

par

celles

définies

dans

*

config.properties

*

.

Ici

on

utilise

aussi

la

possibilité

de

surcharger

ces

valeurs

par

une

référence

à

un

fichier

qui

sera

précisé

par

une

option

au

lancement

de

la

JVM

(Ex

:

*\

-Dapplication.config.location=/tmp/foo.properties

*

).

Afin

que

le

propertyConfigurer

ne

lève

pas

une

exception

au

cas

cette

dernière

possibilité

n'est

pas

utilisée

on

positionne

une

des

ces

propriétés

(

*

ignoreResourceNotFound

*

)

pour

qu'il

ignore

les éventuelles ressources absentes. {note} h2.

les éventuelles ressources absentes.

L'héritage

...

de

...

configuration

...

Spring

...

n'oblige

...

pas

...

à

...

saisir,

...

dans

...

toutes

...

les

...

définitions

...

de

...

beans

...

,

...

les

...

mêmes

...

propriétés.

...

Pour

...

cela,

...

il

...

est

...

possible

...

d'utiliser

...

le

...

mot-clé

...

parent

...

.

...

Le « parent » a un attribut abstract="true"

...

car

...

il

...

ne

...

doit

...

pas

...

être

...

créé

...

en

...

mémoire

...

par

...

Spring

...

.

...

Cette

...

notation

...

permet

...

de

...

se

...

rapprocher

...

de

...

l'héritage

...

Java

...

qui

...

est

...

beaucoup

...

utilisé

...

dans

...

esup-commons

...

.

...

Exemple

...

d'un

...

bean « parent » ayant aussi lui-même un « parent » :

Bloc de code
 un «&nbsp;parent&nbsp;» :

{code}
<bean
  id="abstractApplicationAwareBean"
  parent="abstractI18nAwareBean"
  abstract="true">
    <property name="applicationService" ref="applicationService" />
</bean>
{code}

{note}
Remarque

L'attribut

*

scope

*

(voir

ci-après)

n'est

pas

héritable,

il

est

donc

inutile

de

le

préciser

pour

un bean abstrait.

Vérification des beans

Les beans manipulés par Spring n'ont pas, par défaut, de dépendances particulières avec Spring.

Il est, par contre, possible de sciemment introduire une dépendance avec Spring pour obtenir des services supplémentaires.

Faire en sorte que votre bean implémente l'interface InitializingBean de Spring en fait partie. Cette interface vous oblige à implémenter une méthode afterPropertiesSet qui sera appelée par Spring juste après l'initialisation du bean. Cette méthode vous permet de vérifier que toutes les propriétés sont bien initialisées. Si ce n'est pas le cas, vous pouvez, par exemple, lever une exception ou affecter une valeur par défaut.

On trouvera par exemple :

Bloc de code
 _bean_ abstrait.
{note}

h2. Vérification des _beans_

Les _beans_ manipulés par _Spring_ n'ont pas, par défaut, de dépendances particulières avec _Spring_.

Il est, par contre, possible de sciemment introduire une dépendance avec _Spring_ pour obtenir des services supplémentaires.

Faire en sorte que votre _bean_ implémente l'interface *InitializingBean* de _Spring_ en fait partie. Cette interface vous oblige à implémenter une méthode *afterPropertiesSet* qui sera appelée par _Spring_ juste après l'initialisation du _bean_. Cette méthode vous permet de vérifier que toutes les propriétés sont bien initialisées. Si ce n'est pas le cas, vous pouvez, par exemple, lever une exception ou affecter une valeur par défaut.

On trouvera par exemple :

{code}
public void afterPropertiesSet() {
  super.afterPropertiesSet();
  if (!StringUtils.hasText(exceptionView)) {
    exceptionView = DEFAULT\__SERVLET_\_EXCEPTION_VIEW;
    logger.info(getClass() + ": no exceptionView set, using default \[" + exceptionView + "\]");
  }
}
{code}

h2. Portée des beans

_Spring_ offre une notion de portée (*scope*).

Par défaut, un _bean_ est de portée *singleton*. _Spring_ crée une seule instance de ce _bean_ pour toute la durée d'exécution de l'application.

Il existe aussi des portées *session* et *request* qui, respectivement, permettent d'avoir une instance du _bean_ par session utilisateur (au sens d'une application web) ou par requête (au sens HTTP). Cette notion est particulièrement intéressante pour les contrôleurs web d'une application. Ces derniers sont en général des _beans_ de portée *session*, comme par exemple :
{code}

Portée des beans

Spring offre une notion de portée (scope).

Par défaut, un bean est de portée singleton. Spring crée une seule instance de ce bean pour toute la durée d'exécution de l'application.

Il existe aussi des portées session et request qui, respectivement, permettent d'avoir une instance du bean par session utilisateur (au sens d'une application web) ou par requête (au sens HTTP). Cette notion est particulièrement intéressante pour les contrôleurs web d'une application. Ces derniers sont en général des beans de portée session, comme par exemple :

Bloc de code
<bean id="administratorsController"
  class="[...].formation.web.controllers.AdministratorsController"
  parent="abstractContextAwareController"
  scope="session" />
{code}

Usuellement,

...

un

...

bean

...

de

...

scope

...

request

...

peut

...

faire

...

référence,

...

via

...

ses

...

propriétés,

...

à

...

un

...

bean

...

de

...

scope

...

session

...

ou

...

singleton

...

.

...

De

...

même,

...

un

...

bean

...

de

...

scope

...

session

...

peut

...

faire

...

référence

...

à

...

un

...

bean

...

de

...

scope

...

singleton

...

.

...

Une

...

bonne

...

architecture

...

nous

...

amène

...

d'ailleurs

...

à

...

utiliser

...

dans

...

ce

...

sens

...

l'injection

...

de

...

beans.

...

Par

...

défaut,

...

la

...

réciproque

...

provoque

...

une

...

exception

...

...

...

mais

...

il

...

est

...

cependant

...

possible

...

de

...

réaliser

...

cette

...

réciproque

...

par

...

le

...

biais

...

de

...

l'

...

aop

...

,

...

et

...

cela

...

très

...

simplement.

...

Concrètement

...

si

...

nous

...

voulons

...

ici

...

injecter

...

le

...

bean

...

administratorsController

...

qui

...

est

...

de

...

scope

...

session

...

dans

...

un

...

bean

...

de

...

scope

...

singleton,

...

on

...

utilisera

...

la

...

balise

...

aop:scoped-proxy

...

comme

...

ceci

...

dans

...

la

...

déclaration

...

du

...

bean

...

administratorsController :

Bloc de code
* :
\\
{code}
<bean id="administratorsController"
  class="[...].formation.web.controllers.AdministratorsController"
  parent="abstractContextAwareController"
  scope="session">
 <aop:scoped-proxy/>
</bean>
{code}

Pour

...

ce

...

faire,

...

on

...

aura

...

pris

...

soin

...

de

...

déclarer

...

comme

...

il

...

se

...

doit

...

l'espace

...

de

...

noms

...

aop,

...

avec

...

dans

...

la

...

balise

...

racine

...

du

...

fichier

...

de

...

configuration

...

de

...

beans

...

Spring

...

ceci

...

:

{
Bloc de code
}
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"        
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" >
...
</beans>
{code}


{HTMLcomment}

h2. Récupération des _beans_

Il est possible de récupérer un _bean_ à partir de son nom à partir du code JAVA. La classe *BeanUtils* fournie par _esup-commons_ V1 n'est plus utilisée.

On utilise un mécanisme interne à Spring basé sur l'implémentation de *

HTML Comment

Récupération des beans

Il est possible de récupérer un bean à partir de son nom à partir du code JAVA. La classe BeanUtils fournie par esup-commons V1 n'est plus utilisée.

On utilise un mécanisme interne à Spring basé sur l'implémentation de org.springframework.context.ApplicationContextAware

...

esup-commons

...

V2

...

fournit

...

une

...

telle

...

implémentation

...

qu'il

...

suffit

...

de

...

déclarer

...

dans

...

un

...

fichier

...

de

...

configuration

...

Spring

...

(ex

...

:

...

properties/applicationContext.xml

...

)

...

:

...

Bloc de code

...


<bean id="app_context" class="org.esupportail.commons.context.ApplicationContextHolder"/>

...

Depuis

...

le

...

code

...

java,

...

on

...

utilisera

...

:

...

Bloc de code

...


ApplicationContext springContext = ApplicationContextHolder.getContext();
DomainService domainService = (DomainService) springContext.getBean("domainService");

...

Avertissement
  • L'utilisation

...

  • de

...

  • cette

...

  • méthode

...

  • devrait

...

  • rester

...

  • exceptionnelle

...

  • (mode

...

  • batch

...

  • par

...

  • exemple)

...