Ces instructions sont à refaire chez vous sur votre ordinateur pour pouvoir travailler chez vous.
Pour utiliser Spring, il nous faut récupérer les jars de Spring dont nous aurons besoin. Plutôt que de le faire à la main, nous allons utiliser Maven.
Vérifiez que Maven est bien installé avec la commande:
$ mvn -vSi ce n'est pas le cas installez-le depuis ce site.
Nous n'allons pas utiliser Maven directement mais plutôt l'IDE IntelliJ qui fournit une très bonne intégration avec Maven
IntelliJ a créer la structure d'un projet Maven. Votre code ira dans src/main/java. Il y a aussi un fichier XML pom.xml qui contient les paramètres de configuration de Maven.
Nous allons maintenant indiquer à Maven que nous voulons utiliser une partie du framework Spring
. Pour cela, il faut rajouter dans le fichier pom.xml les dépendances suivantes. Il faut rajouter au-dessus de la balise </project>
Si le fichier pom.xml proposé par IntelliJ contient déjà une balise properties, il faut la supprimer pour la remplacer par la balise fournie ci-dessous.
<properties> <org.springframework.version>6.0.13</org.springframework.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.target>17</maven.compiler.target> <maven.compiler.source>17</maven.compiler.source> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${org.springframework.version}</version> </dependency> </dependencies>
Si vous utilisez une autre version du SDK, il faut adapter les champs maven.compiler.
Pour qu'IntelliJ télécharge les librairies correspondant aux balises dependency, il faut
cliquer sur l'icone .
Si vous allez dans File > Project Structure > Librairies, vous devriez voir que IntelliJ a téléchargé les librairies de Spring.
Toutes vos classes doivent être dans le package fr.uge.jee.printers.
Le main
de la classe Application
ci-dessous crée un SimpleMessagePrinter
et appelle sa méthode printMessage
.
public class SimpleMessagePrinter { public void printMessage(){ System.out.println("Hello World!"); } } public class Application { public static void main(String[] args) { var printer = new SimpleMessagePrinter(); printer.printMessage(); } }
On veut que SimpleMessagePrinter
soit géré par le conteneur IoC
de Spring.
Créer un fichier config-printers.xml
où vous allez déclarer le bean correspondant à SimpleMessagePrinter
. Vous pouvez partir du fichier ci-dessous:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <bean id="..." class="..."/> </beans>
Le fichier config-printers.xml
doit se trouver dans le répertoire src/main/resources/.
Une fois le bean déclaré, il faut créer un conteneur IoC de Spring à partir du fichier config-printers.xml avec le code suivant:
ApplicationContext context = new ClassPathXmlApplicationContext("config-printers.xml");
Modifiez la classe Application
comme demandé.
Cet exercice continu l'exercice précédent. Toutes vos classes doivent être dans le package fr.uge.jee.printers.
Nous voulons définir plusieurs afficheurs de message.
Créez une interface MessagePrinter
et faites en sorte que SimpleMessagePrinter
implémente de cette interface.
Créez une classe FrenchMessagePrinter
qui implémente cette interface et qui affiche le message en français.
Faites changer votre afficheur de message pour un FrenchMessagePrinter
en utilisant seulement le fichier config-printers.xml
Changez votre fichier de configuration config-printers.xml
pour avoir un bean pour chacun des MessagePrinter
. Modifiez ensuite votre classe Application
pour instantier chacun de ces beans et appeler leur méthode printMessage
.
La classe CustomizableMessagePrinter
a un constructeur qui permet configurer le message afficher.
package fr.uge.jee.printers; public class CustomizableMessagePrinter implements MessagePrinter { private String message; public CustomizableMessagePrinter(){ this.message="Custom Hello World"; } public CustomizableMessagePrinter(String message){ this.message=message; } @Override public void printMessage() { System.out.println(message); } }
Changez votre config-printers.xml pour rajouter un bean pour CustomizableMessagePrinter
. Dans votre classe Application
, instanciez le bean correspondant à la classe CustomizableMessagePrinter
. Quel constructeur est appelé ?
Il est possible de passer un argument pour le constructeur au moment de la création du bean. Pour cela, il faut rajouter dans config-printers.xml
la propriété suivante dans le bean concerné.
<bean id="..." class="..."> <constructor-arg value="Argument for the constructor"/> </bean>
Changez votre config-printers.xml pour qu'il définisse un bean pour la classe CustomizableMessagePrinter
créé avec le message "Hello from the config.xml"
.
Cet exercice continue les deux exercices précédents. Toutes vos classes doivent être dans le package fr.uge.jee.printers.
On continue l'exercice précédent. On va dans un premier temps rajouter une classe CountMessagePrinter
qui quand on appelle printMessage
affiche un
message du type "This message number 1"
et
incrémente ce nombre au prochain appel.
Dans votre fichier de configuration, rajoutez un bean pour CountMessagePrinter
.
MessagePrinter printer = context.getBean("printerServiceC ount",MessagePrinter.class); printer.printMessage(); printer.printMessage(); printer.printMessage(); MessagePrinter printer2 = context.getBean("printerServiceCount",MessagePrinter.class); printer2.printMessage();
Expliquez l'affichage ci-dessous ? Quel design pattern est mis en oeuvre par le conteneur IoC ?
This is message number 0 This is message number 1 This is message number 2 This is message number 3
On peut changer la façon dont le conteneur IoC crée les beans en changeant le scope du bean. Pour plus d'information sur les scopes d'un bean, vous pouvez vous référer à la documentation de Spring.
Changez votre fichier de configuration pour qu'un CountMessagePrinter
différent soit crée à chaque appel à getBean
.
Le but de la fin de l'exercice est comprendre quand les beans sont instantiés. Est-ce que c'est au moment de la création de ApplicationContext
ou au moment de l'appel au premier getBean
pour ce bean ?
Ecrivez une classe SlowConstructionMessagePrinter
qui simule un bean lent à instantié en attendant 5 secondes dans le constructeur. Definissez un bean correspondant dans le fichier de configuration.
A quel moment sont instantiés les beans ?
En regardant la documentation de Spring, faites en sorte que le bean correspondant à SlowConstructionMessagePrinter
ne soit instantié à la création de ApplicationContext
.
Quel est l'inconvéniant majeur de déférer l'instantition des beans ?
Cet exercice continue les deux exercices précédents. Toutes vos classes doivent être dans le package fr.uge.jee.bookstore. Votre fichier de configuration se nommera config-bookstore.xml
.
Codez l'exemple du cours sur Library
et Book
. Dans votre fichier de configuration XML, créez 3 beans pour 3 livres et une Library
qui contient deux de ces livres. Créez un classe Application
pour créez le bean de la Library
et l'afficher avec sa méthode toString
.
Utilisez autowire="constructor"
pour définir le bean associé à Library
en pensant bien à supprimer
les arguments! Qu'observez vous ?
Toutes vos classes doivent être dans le package fr.uge.jee.onlineshop et votre fichier XML doit s'appeler config-online.xml.
Dans cet exercice, on veut faire un sorte de modéliser un magasin en ligne. Le but est simplement de faire construire par le conteneur IoC de Spring un bean pour OnlineShop
que l'on puisse entièrement configurer. La classe OnlineShop
ne fait rien à part afficher sa configuration.
Le magasin peut avoir jusqu'à deux modes de livraison: le mode classique et le mode par drone. Le mode classique a un délai de livraison moyen qui sera injecté depuis le fichier de configuration. De plus, le magasin offre jusqu'à deux assurances : l'assurance pour les retours (qui peut être soit uniquement réservée aux membres soit ouverte à tous) et l'assurance contre le vol.
public class OnlineShop { private final String name; private final Set<Delivery> deliveryOptions; private final Set<Insurance> insurances; .... public void printDescription(){ System.out.println(name); System.out.println("Delivery options"); deliveryOptions.forEach(opt -> System.out.println("\t"+opt.description())); System.out.println("Insurance options"); insurances.forEach(insurance -> System.out.println("\t"+insurance.description())); } }
Ecrivez les classes et les interfaces nécessaires et complétez la classe OnlineShope.
La situation est simplifiée à l'extrême. On vous demande juste de faire une interface pour les assurances avec simplement une méthode String description()
et une interface pour les méthodes de livraison avec aussi une méthode String description()
Ecrivez un fichier XML et une classe Application
dont le main
utilise le conteneur IoC de Spring pour créer un magasin et affiche sa description. On veut le résultat ci-dessous:
Amazon Delivery options Delivery by drone Standard Delivery with a delay of 5 days Insurance options Return insurance only for members
En modifiant uniquement votre fichier XML faites en sorte que la configuration du magasin change pour obtenir l'affichage ci-dessous. Copiez votre fichier de configuration dans config-onlineshopv2.xml
.
AhMaZone Delivery options Standard Delivery with a delay of 999 days Insurance options Return insurance Thief insurance
Modifier votre fichier de configuration pour ne pas avoir besoin de vous baser
sur le nom des beans. Copiez votre fichier de configuration dans config-onlineshopv3.xml
.
Il est possible d'omettre le champ id
dans la définition d'un bean. Votre fichier config-onlineshopv3.xml
ne doit contenir aucune id
.