SpEL: Spring Expression Language

SpEL: Can you SpEL(l) it, please?
Oui, c'est Spring Expression Language.spring-mini-logo.png
C'est quoi SpEL?
A quoi peut-il servir ?
Pourquoi encore apprendre une nouvelle notion (nouveau truc)?

Cela fait beaucoup de questions en même temps.
Ce billet tente de donner des réponses. Surtout, il illustre le thème par des exemples concrets.

Pour la première question: C'est quoi SpEL? La réponse donnée par springsource.org :
The Spring Expression Language (SpEL for short) is a powerful expression language that supports querying and manipulating an object graph at runtime.

Ok, je vois que ce n'est pas encore très clair.
Pour expliciter un peu, disons que, dans Spring version antérieure à 3, les liaisons entre les beans ne peuvaient être que statiques.
Ainsi la configuration de Spring se faisait ainsi:

 - soit une référence statique d'un bean à un autre bean, 
 - soit une définition statique d'une propriété simple (type primitif).

D'où la question naturelle:

Q. Si on veut des liaisons résolues dynamiquement et des valeurs calculées au Runtime, est-ce possible?

R. Oui. C'est ici que SpEL est utile. Il permet de:

   référencer dynamiquement des beans,
   invoquer des méthodes et accéder aux propriétés des beans,
   utiliser des opérations arithmétiques, logique et de comparaison,
   tester des expressions régulières, ... etc.

Q. Peut-on avoir un premier exemple, car ce n'est pas clair du tout?

R. Oui, commençons par ajouter le jar nécessaire à notre projet java JSE:
spring-expression-3.1.1.RELEASE.jar

Puis déclarons nos beans dans le fichier de configuration xml de Spring:

<bean id="myBean" class="fr.netapsys.demo.MyBean"> 
   <property name="dateDuJour" value="#{new java.util.Date()}"/>
</bean>

Whaooo! ce n'est pas mieux. C'est encore flou voire compliqué!

Attendons un peu les explications:

Une expression dans SpEL est toujours de la forme "#{ ........}".

Exemple, l'expression #{new java.util.Date()} permet donc de setter la propriété dateDuJour du bean "myBean" avec
le résultat dynamique de l'instruction java new Date().

Là, je vois vos questions arriver:

Q. Quelle valeur est résolue dynamiquement lorsque le bean est initialisé en mode tardif (lazy loading) par Spring?

Q. Quelle valeur est résolue lorsque le bean est un singleton? un prototype?

R. Ça fait encore beaucoup de questions (complexes).

Des exemples concrets seront fournis dans un article prochain afin de répondre à toutes ses questions.

Pour l'instant, poursuivons la découverte de SpEL avec ce deuxième exemple un peu plus avancé:

<bean id="utilBean"  class="fr.netapsys.demo.utils.UtilBean"
   p:dateDuJour="#{new java.util.Date()}"/>

<bean id="myBean" class="fr.netapsys.demo.MyBean"
 p:proprietaire="#{systemProperties['user.name'] }" 
 p:dateDay=
   "#{new java.text.SimpleDateFormat('dd/MM/yy').format(
    utilBean.dateDuJour)}" 
/>

Celui-ci a pour but d'illustrer l'intérêt de SpEL en liaison dynamique entre beans.

Q. Pouvez-vous expliquer un peu? Ce n'est pas évident!

R. Oui. Tentons :

Le bean ayant l'id="utilBean" possède un attribut "dateDuJour" initialisé dynamiquement avec la date du jour.

Jusque là, rien de nouveau nous avons reproduit l'exemple 1.

Ensuite, le bean id="myBean" possède deux attributs:
Le premier attribut "proprietaire" est initialisé avec l'expression

     "#{systemProperties['user.name'] }"

Le second "dateDay" initialisé dynamiquement avec la valeur
de l'attribut "dateDuJour" d'un autre bean "utilBean".

Il nous reste à détailler l'expression

"#{systemProperties['user.name'] }" 

Elle permet de résoudre dynamiquement la valeur de la propriété système 'user.name'.
C'est à dire que la variable prédéfinie dans SpEL nommée systemsProperties accède à la variable d'environnement du système (OS).

Q. Avec ces explications, est ce plus clair?

R. Oui mais, ...

J'essaierai la prochaine fois d'être encore plus ...Comment dire déjà!

D'ici là n'hésitez pas à reproduire ces deux exemples sous eclipse avec les dépendances maven :

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
		 <version>3.1.1.RELEASE</version>
	<exclusions>
	    <exclusion>
	      <groupId>commons-logging</groupId>
	       <artifactId>commons-logging</artifactId>
	    </exclusion>
       </exclusions>
</dependency>
  <!-- optionel, CGLIB pour @Configuration classes -->
 <dependency>
	<groupId>cglib</groupId>
	<artifactId>cglib-nodep</artifactId>
	<version>2.1_3</version>
 </dependency>
<!-- test -->
<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8</version>
      <scope>test</scope>
 </dependency>

Prochainement, une démo illustrera le même thème mais elle utilisera exclusivement les annotations. En particulier l'annotation @Value.
Nous réponderons aux deux questions évoquées précédemment:

Q. Quelle valeur est résolue dynamiquement lorsque le bean est initialisé en mode tardif (lazy loading) par Spring?

Q. Quelle valeur est résolue lorsque le bean est un singleton? un prototype?

Un commentaire

Laisser un commentaire

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

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.