Spring IOC

Introduction

Spring est un framework open source J2EE pour les applications n-tiers, dont il facilite le développement et les tests. Il est considéré comme un conteneur dit « léger », c’est-à-dire une infrastructure similaire à un serveur d’application J2EE. Il prend donc en charge la création d’objets et la mise en relation d’objets par l’intermédiaire d’un fichier de configuration qui décrit les objets à fabriquer et les relations de dépendances entre ces objets.

Le gros avantage par rapport aux serveurs d’application est qu’avec Spring, vos classes n’ont pas besoin d’implémenter une quelconque interface pour être prises en charge par le framework (au contraire des serveurs d’applications J2EE et des EJBs). C’est en ce sens que Spring est qualifié de conteneur « léger ».

Spring s’appuie principalement sur l’intégration de trois concepts clés :

  1. l’inversion de contrôle ou injection de dépendance (IoC).
  2. la programmation orientée aspect (AOP).
  3. une couche d’abstraction.

Ce framework, grâce à sa couche d’abstraction, ne concurrence pas d’autres frameworks dans une couche spécifique d’un modèle architectural MVC mais s’avère un framework multi-couches pouvant s’insérer au niveau de toutes les couches.

Nous allons aborder dans ce premier tutoriel le premier concept : IoC (Inversion Of Control).

A quoi sert l’Inversion de Contrôle? Le noyau de Spring permet l’injection de propriétés dans les beans rendant ainsi possible une inversion de contrôle.

Le principal avantage est de composer les beans de façon plus déclarative plutôt que de façon impérative dans le programme. On peut, par exemple, définir les beans par le biais de fichiers de configuration en XML.

Site Officiel

Vous trouverez le site officiel de Spring à l’adresse suivante : http://www.springsource.org/

Wikipédia

Je vous invite à consulter les articles français et anglais de la célèbre encyclopédie Wikipédia à propos du Framework Spring.

Tutoriel

Avant d’entamer ce tutoriel, vérifiez que vous avez bien les pré requis :

  • le JDK doit être installé sur votre machine.
  • Eclipse doit être installé sur votre machine (il est conseillé d’utiliser la version Eclipse IDE for Java EE Developers pour ce tutoriel).


Création du projet dans Eclipse

  • Lancer Eclipse.
  • On crée un nouveau projet. Pour cela on ouvre le menu File → New → Java Project.
  • La fenêtre de wizard apparaît alors. Nous allons simplement indiquer ici le nom du projet dans le champ Project name : sf-sample-spring-ioc
  • On peut ensuite cliquer sur Finish. Le projet apparaît alors dans l’onglet Project Explorer qui répertorie les différents projets du workspace.


Ajout des librairies

  • Il faut télécharger le Framework Spring à l’adresse suivante : Spring Framework 2.5.6
  • On va ensuite extraire le contenu de l’archive zip dans notre projet. Pour ce faire, on ouvre un explorateur de fichiers, pour accéder au workspace (sous Ubuntu il sera situé par défaut dans /home/user/workspace), on va dans le répertoire du projet, dans lequel on crée un nouveau répertoire lib qui contiendra les librairies. On extrait ensuite l’archive dedans.

Si le répertoire lib n’apparait pas dans votre projet sous Eclipse, sélectionnez votre projet et appuyez sur F5 pour rafraîchir le projet.

  • Il faut ensuite spécifier à Eclipse dans notre projet qu’on a ajouté une librairie pour pouvoir l’utiliser. On fait un clic droit sur le projet dans le package explorer qui ouvre un menu contextuel : on ouvre Build Path → Configure Build Path. On clic sur l’onglet Libraries, puis sur le bouton add JARS…. Il suffit ensuite d’ajouter les bibliothèques suivantes spring.jar, spring-core.jar, commons-logging.jar, et junit-4.4.jar du Framework Spring situées dans les sous répertoires de lib du projet sf-sample-spring-ioc. On valide les modifications sur le projet en cliquant sur OK. Nous sommes maintenant prêts à débuter le code!


Implémentation de la première classe

Nous allons désormais créer une classe java tout ce qu’il y a de plus simple. C’est un exemple volontairement simpliste afin de se concentrer sur l’inversion de Contrôle de Spring. Vous allez voir c’est un jeu d’enfant ! Nous allons prendre l’exemple d’une interface Logger qui définit les méthodes proposées par un service de logging.

On développera deux implémentations de cette interface ConsolLogger et MailLogger qui génèrent respectivement des logs dans la console et par email, afin de voir comment on peut simplement instancier des implémentations différentes de l’interface Logger en utilisant Spring.

  • On se place sur le répertoire src du projet sf-sample-spring-ioc, puis on fait un clic droit, New → Interface.
  • La fenêtre de wizard New Java Interface est normalement apparue. On indique dans le champ Package com.scub.foundation.tutorial.spring.ioc.interfaces et on entre dans Name le nom Logger puis on clique sur Finish.
  • Voici le code de l’interface Logger commentée ci-dessous :
package com.scub.foundation.tutorial.spring.ioc.interfaces;
 
/**
 * Service de qui permet de générer des logs
 * @author Scub-Foundation
 */
public interface Logger {
 
	/**
	 * Génère un log
	 * @param message message de log
	 */
	public void log(String message);
}
  • Voici le code de l’implémentation ConsoleLogger :
package com.scub.foundation.tutorial.spring.ioc.implementations;
 
import java.text.SimpleDateFormat;
import java.util.Date;
 
import com.scub.foundation.tutorial.spring.ioc.interfaces.Logger;
 
/**
 * Implémentation de l'interface Logger
 * Génère des logs dans une console 
 * @author Scub-Foundation
 */
public class ConsoleLogger implements Logger {
 
	/**
	 * {@inheritDoc} dans la console
	 */
	@Override
	public void log(String message) {
		System.out.println(new SimpleDateFormat("dd/MM/yyyy").format(new Date()) +" : "+message);
	}
 
}
  • Voici le code de l’implémentation MailLogger :
package com.scub.foundation.tutorial.spring.ioc.implementations;
 
import com.scub.foundation.tutorial.spring.ioc.interfaces.Logger;
 
/**
 * Implémentation de l'interface Logger Génère des logs par mail.
 * @author Scub-Foundation
 */
public class MailLogger implements Logger {
 
	/** Destinataire */
	private String emailDestinataire;
 
	/**
	 * Accesseur en écriture
	 * @param emailDestinataire le nouveau emailDestinataire
	 */
	public void setEmailDestinataire(String emailDestinataire) {
		this.emailDestinataire = emailDestinataire;
	}
 
	/**
	 * {@inheritDoc} par mail Pour simplifier on se contente d'afficher le log
	 * dans la console avec un destinataire sans réellement envoyer un mail
	 */
	@Override
	public void log(String message) {
		System.out.println("envoi du log " + message
				+ " à l'adresse un email suivante : " + this.emailDestinataire);
	}
}

Configuration de Spring

Pour instancier des implémentations de l’interface Logger, nous allons utiliser un fichier XML, que l’on nommera spring.context.xml que l’on va créer à la racine du répertoire src du projet. Pour le créer il suffit de faire :

  • Clic droit sur src dans le package explorer
  • New → Other → XML avec comme nom spring.context.xml

Ce fichier va contenir les lignes suivantes :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
  "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<bean id="logger1"
		class="com.scub.foundation.tutorial.spring.ioc.implementations.ConsoleLogger">
	</bean>
 
	<bean id="logger2"
		class="com.scub.foundation.tutorial.spring.ioc.implementations.MailLogger">
		<property name="emailDestinataire">
			<value>stephane.traumat@scub.net</value>
		</property>
	</bean>
</beans>

Dans le fichier on déclare deux implémentations différentes de l’interface Logger sous forme de beans. On initialise l’attribut destinataire pour le logger2 qui est de type MailLogger. On pourrait aussi spécifier les méthodes init-method et destroy-method de la classe à appeler à la création de l’objet (init()) et à la destruction de l’objet (destroy()).

Il reste ensuite à utiliser le fichier XML pour instancier les beans. Pour cela, nous allons créer une classe de test unitaire JUnit.

  • On se place sur le répertoire src du projet sf-sample-spring-ioc dans le package explorer.
  • clic droit New → Junit Test Case
  • Dans la fenêtre du wizard, on indique dans le champ package com.scub.foundation.tutorial.spring.ioc.test, on saisit comme nom TestSpringIoC et on coche la case setUp() puis on valide en cliquant sur Finish.

On remplit la nouvelle classe en remplissant la méthode setUp() et en ajoutant une méthode de test testSpringIoC(). Voici le code de la classe :

package com.scub.foundation.tutorial.spring.ioc.test;
 
import static junit.framework.Assert.assertNotNull;
 
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
 
import com.scub.foundation.tutorial.spring.ioc.implementations.ConsoleLogger;
import com.scub.foundation.tutorial.spring.ioc.implementations.MailLogger;
 
/**
 * @author Scub-Foundation
 */
public class TestSpringIoC {
 
	// usine à beans
	private ListableBeanFactory bf;
 
	/**
	 * @throws Exception
	 */
	@Before
	public void setUp() throws Exception {
		bf = new XmlBeanFactory(new ClassPathResource("spring.context.xml"));
	}
 
	/**
	 * Méthode de test 
	 */
	@Test
	public void testSpringIoC() {
		// récupération par leur clé des beans [Logger] du fichier xml Spring
 
		// Logging dans la console
		ConsoleLogger logger1 = (ConsoleLogger) bf.getBean("logger1");
		assertNotNull("Le logger 1 n'a pas été instancié", logger1);
		logger1.log("Ceci est un log à destination de la console");
 
		// Logging par mail 
		MailLogger logger2 = (MailLogger) bf.getBean("logger2");
		assertNotNull("Le logger 2 n'a pas été instancié", logger2);
		logger2.log("Ceci est un log à destination d'un email");
	}
}

La méthode setUp() du test Unitaire crée une bean factory à partir du fichier XML que l’on a montré plus haut, ce qui va instancier nos Objets de type ConsoleLogger et MailLogger que l’on récupère et affiche dans la méthode testSpringIoC() pour bien montrer qu’ils ont été correctement instanciés.
Cet exemple simple nous montre qu’avec Spring IoC on peut instancier des Objets par le biais d’un fichier XML et non de manière impérative dans le programme. Il est très facile de changer un logger d’implémentation, il suffit d’aller modifier une ligne dans le fichier de configuration xml Spring.

Exécution du Test Unitaire

On peut alors exécuter le test Unitaire. Il suffit de lancer la classe TestSpringIoC, pour cela on sélectionne la classe dans le package explorer, clic droit dessus puis Run As → JUnit Test. On a alors dans la console les messages envoyés qui doivent être affichés comme sur la copie d’écran ci dessous :


Télécharger les sources

Les sources du projet Eclipse pour ce tutoriel sont téléchargeables sur Source Forge à l’adresse suivante.