Spring
Introduction à Spring
Aperçu
Instructeur : Ghada Feki
Focus : loC (Inversion de Contrôle).
Plan
Introduction
Concepts de conteneur léger.
Aperçu et exemples d'utilisation.
IoC : Inversion de Contrôle, injection de dépendances.
Programmation orientée aspect.
Tests unitaires en isolation.
Approche MVC avec Spring MVC.
Implémentation
Programmation par contrat.
Singleton.
Cycle de vie des beans.
Beans, BeanFactory et ApplicationContext.
Gestion des propriétés, "collaborateurs".
Méthodes d'injection de dépendances.
Définition et héritage de bean abstrait.
MODÈLE DAO, ACCÈS AUX DONNÉES AVEC JDBC.
Classes abstraites pour la prise en charge de DAO.
Utilisation de JDBC via les API d'encapsulation Spring DAO.
Introduction
Spring Framework est open source.
Il construit et définit l'infrastructure d'une application Java.
Facilite le développement et les tests.
Ce que Spring peut faire
IA générative : Intégrez l'IA dans les applications Spring.
Microservices : Fournissez rapidement des fonctionnalités de qualité production avec des microservices évolutifs indépendamment.
Réactif : Architecture asynchrone et non bloquante pour une meilleure utilisation des ressources.
Cloud : Prend en charge le code sur n'importe quel cloud, connectant et mettant à l'échelle les services.
Applications Web : Frameworks pour des applications Web rapides, sécurisées et réactives connectées à n'importe quel magasin de données.
Sans serveur : Flexibilité ultime, mise à l'échelle à la demande et à zéro en l'absence de demande.
Piloté par les événements : Intégrez-vous à votre entreprise, réagissez aux événements commerciaux, agissez sur les données de diffusion en continu en temps réel.
Lot : Tâches automatisées, traitement hors ligne des données à un moment opportun.
Concepts de conteneur léger
Spring est un conteneur "léger", similaire à un serveur d'applications Java EE.
Il prend en charge la création d'objets et la gestion des relations via un fichier de configuration qui décrit les objets et leurs dépendances.
Avantage par rapport aux serveurs Java EE : Spring n'exige pas que les classes implémentent des interfaces spécifiques pour être prises en charge par le framework.
C'est pourquoi Spring est appelé un conteneur "léger".
Intégration des concepts clés
Spring repose principalement sur l'intégration de trois concepts clés :
L'inversion de contrôle (IoC) est assurée de deux manières différentes : la recherche de dépendances et l'injection de dépendances.
Programmation orientée aspect (AOP).
Couche d'abstraction : Permet une intégration facile d'autres frameworks et bibliothèques.
Réalisé en ajoutant des couches d'abstraction spécifiques pour des frameworks particuliers, ce qui facilite l'intégration de modules tels que l'envoi de courrier.
Architecture du Framework
La couche d'abstraction de Spring n'est pas en concurrence avec d'autres frameworks dans des couches spécifiques du modèle architectural MVC.
Il s'agit d'un framework multicouche qui peut être inséré à toutes les couches : modèle, vue et contrôleur.
Permet l'intégration avec des frameworks tels que Hibernate pour la couche de persistance, ou Struts et JavaServer Faces pour la couche de présentation.
Spring Framework Runtime
L'architecture de Spring Framework Runtime est structurée en modules, chacun répondant à des préoccupations spécifiques. Voici une ventilation, en commençant par le noyau :
Couche de conteneur central
Noyau : Fournit des fonctionnalités fondamentales.
Beans : Gère les beans, les composants centraux des applications Spring.
Contexte : Offre un contexte à l'application en cours d'exécution.
Langage d'expression : Fournit un langage d'expression puissant pour interroger et manipuler des objets au moment de l'exécution.
AOP (Programmation orientée aspect)
Aspects : Permet la modularisation des préoccupations transversales, telles que la journalisation et la gestion des transactions.
Instrumentation : Prend en charge l'instrumentation du code pour la surveillance et le profilage.
Couche d'accès/d'intégration aux données
JDBC : Fournit une prise en charge de JDBC (Java Database Connectivity) pour interagir avec les bases de données.
ORM : S'intègre aux outils de mappage objet-relationnel comme Hibernate pour la persistance des données.
OXM : Prend en charge le mappage objet-XML pour la sérialisation et la désérialisation des données XML.
JMS : Permet l'intégration avec Java Message Service (JMS) pour la messagerie asynchrone.
Transactions : Gère les transactions pour garantir la cohérence des données.
Couche Web
Servlet Web : Prend en charge l'API Servlet pour la création d'applications Web.
Portail Web : Permet la création d'applications basées sur des portlets.
Struts : S'intègre au framework Struts.
Test : Facilite les tests unitaires et d'intégration.
Aperçu et exemples d'utilisation
Le framework est organisé en modules, tous basés sur le module Spring Core.
Spring Core implémente l'inversion de contrôle (injection de dépendances).
Il gère et configure le conteneur.
Le cœur de Spring est basé sur une usine générique de composants IT, appelés beans, et un conteneur pour les stocker.
Il permet de contrôler ces composants de l'extérieur via l'inversion de contrôle.
L'avantage est de composer les beans de manière déclarative plutôt qu'impérative dans le programme.
Les beans peuvent être définis via des fichiers de configuration Java ou XML.
Exemple : Deux beans singleton sont définis.
Le premier est un objet d'accès aux données pour les produits, injecté dans le second, un gestionnaire de produits.
Lors d'une recherche, Spring fournit le gestionnaire de produits, qui utilise l'objet d'accès aux données.
Exemple de configuration :
@Configuration
public class AppConfig {
@Bean
public ClientService clientService(ClientDao clientDao) {
ClientService clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao);
return clientService;
}
@Bean
public ClientDao clientDao() {
return new ClientDaoImpl();
}
}
Modules du framework Spring
Plusieurs modules du framework Spring complètent le cœur pour permettre l'intégration avec d'autres bibliothèques et frameworks :
Spring Context : Étend Spring Core, fournissant une sorte de base de données d'objets.
Il permet de charger des ressources (par exemple, des fichiers de configuration), la propagation d'événements et la création de contexte (par exemple, la prise en charge de Spring dans un conteneur Servlet).
Spring AOP : Permet l'intégration de la programmation orientée aspect.
Spring DAO : Résume l'accès à la base de données, élimine le code redondant et résume les messages d'erreur.
Il fournit la gestion des transactions.
Spring ORM : Intègre les frameworks de mappage objet/relationnel comme Hibernate, JDO ou iBatis avec Spring.
Ce package peut réduire considérablement le code (ouverture/fermeture de session, gestion des erreurs).
Spring Web : Fournit des utilitaires pour les applications Web.
Par exemple, une servlet démarre le contexte (conteneur) lorsqu'une application Web démarre.
Il permet également d'utiliser des requêtes HTTP multiparties et s'intègre au framework Struts.
Spring Web MVC : Implémente le modèle MVC
Schéma des modules Spring
Représentation visuelle des modules Spring et de leurs dépendances :
Spring AOP (Aspects).
Spring ORM (prise en charge d'Ibatis, Hibernate, JDO).
Spring Web (utilitaires).
Spring MVC (modèle, vue, contrôleur).
Spring DAO (gestion des transactions, prise en charge de JDBC, prise en charge de DAO).
Spring Context (exposer via JNDI, prise en charge d'EJB, télécommunication).
Spring Core (utilitaires, contexte, IoC, singleton).
Dépendances d'objets
Les objets de la classe C1 dépendent des objets de la classe C2 si :
C1 a un attribut d'objet de la classe C2.
C1 hérite de la classe C2.
C1 dépend d'un objet de type C3 qui dépend d'un objet de type C2.
Une méthode de C1 appelle une méthode de C2.
IoC : Inversion de contrôle, injection de dépendances
L'inversion de contrôle (IoC) ou l'injection de dépendances est le concept central de Spring.
C'est un modèle de conception pour faciliter l'intégration des composants.
Le concept est basé sur l'inversion de la façon dont les objets sont créés.
En règle générale, si vous souhaitez créer un objet qui en utilise un autre, vous programmeriez quelque chose comme ceci :
Le problème
On vous dit d'utiliser LDAP au lieu d'une base de données pour l'identification.
L'objectif est de rendre un produit standard compatible avec toutes les bases de données et les systèmes d'authentification.
La solution est de séparer les couches et d'utiliser des interfaces, non uniques à Spring.
Problème de configuration
Le problème est de configurer simplement les pilotes et les objets nécessaires et d'intégrer le tout dans l'application.
L'inversion de contrôle entre en jeu ici.
Le but n'est pas de fournir un objet à un autre, mais que l'objet sache lui-même ce dont il a besoin.
Si un objet nécessaire a des dépendances, il doit parvenir à les obtenir, ce qui donne :
Simplification du code
La méthode
getBeanest purement formelle dans cet exemple.Le but est de montrer que le code se réduit à sa forme la plus simple, avec les dépendances déclarées dans la configuration du conteneur.
Ce qu'il fait :
Résout ISecurityBean dans son arborescence de dépendances et trouve la classe d'implémentation.
Crée une instance (dans le cas d'une injection non mutatrice).
Crée des objets dépendants et les définit dans ISecurityBean via ses accesseurs.
Fait récursivement la même chose pour toutes les dépendances des dépendances.
Dépendances réduites
Les dépendances entre les couches sont minimisées.
Une implémentation peut facilement être remplacée par une autre sans mettre en danger la stabilité et l'intégrité de l'ensemble.
La nouvelle implémentation doit être exempte de bogues.
Types d'injection
Il existe trois types d'injection :
Injection de constructeur.
Injection de setter (via des modificateurs).
Injection d'interface.
Injection de constructeur
La dépendance est fournie via le constructeur de la classe.
@Service
public class EmailService {
public void sendEmail(String message) {
System.out.println("Email sent: " + message);
}
}
@Component
public class NotificationService {
private final EmailService emailService;
@Autowired
public NotificationService(EmailService emailService) {
this.emailService = emailService;
}
public void notifyUser(String message) {
emailService.sendEmail(message);
}
}
Injection de setter (modificateur)
Dépendance injectée via un setter.
Cas d'utilisation : Dépendances facultatives (peuvent être modifiées ultérieurement).
@Component
public class NotificationService {
private EmailService emailService;
@Autowired
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
public void notifyUser(String message) {
emailService.sendEmail(message);
}
}
Injection d'interface
Une interface définit la méthode d'injection (moins utilisée dans Spring moderne).
Spring utilise rarement cette approche aujourd'hui (préfère le constructeur/setter).
public interface MessageServiceInjector {
void injectMessageService(EmailService emailService);
}
@Component
public class NotificationService implements MessageServiceInjector {
private EmailService emailService;
@Override
@Autowired
public void injectMessageService(EmailService emailService) {
this.emailService = emailService;
}
public void notifyUser(String message) {
emailService.sendEmail(message);
}
}
Abstraction Spring
Spring offre des abstractions pour gérer :
Mode transactionnel.
Appel EJB.
Création EJB.
Persistance des objets.
Création d'interface Web.
Appel et création de services Web.
Pour ce faire, Spring s'appuie sur IoC et la programmation orientée aspect (AOP).
Programmation orientée aspect
Les composants métier sont souvent pollués par des appels à des composants utilitaires externes.
Complexité du code
Ces appels rendent le code plus complexe et moins lisible.
Un code plus court et plus clair améliore la qualité et la réutilisabilité.
Implications :
Désordre du code.
Faible réutilisabilité.
Qualité inférieure en raison de la complexité du code.
Difficulté d'évolution.
Solution
Externaliser tous les traitements de logique non métier en dehors du composant.
Définir les traitements de manière déclarative sur les points clés de l'algorithme, généralement avant ou après une méthode.
Les traitements utilitaires se produisent souvent au début ou à la fin d'une méthode (par exemple, les appels de journalisation, la validation ou l'annulation des transactions).
Approche :
Décomposition des aspects : Séparer la partie métier de la partie utilitaire.
Programmation de la partie métier : Se concentrer sur la partie variable.
Recomposition des aspects : Définir les aspects.
Types de programmation orientée aspect
Deux techniques AOP avec des avantages et des inconvénients :
Approche statique : La connexion entre l'aspect et la partie métier se fait lors de la compilation ou de la post-production via la manipulation du bytecode.
Cette méthode intrusive n'est pas toujours la plus transparente.
Approche dynamique : La connexion se fait par réflexion au moment de l'exécution.
Plus transparente mais plus lente, avec l'avantage d'être reconfigurable sans recompilation.
Concepts AOP
Concept (Français) | Concept (Anglais) | Description |
|---|---|---|
Point de jonction | Joinpoint | Emplacement dans le code où l'advice est inséré. |
Coupe ou points d'actions | Pointcut | Ensemble de joinpoints, souvent une expression régulière. |
Conseil ou greffon | Advice | Fragment de code inséré au point de jonction (par exemple, journalisation, commit). |
Aspect | Aspect | Ensemble de joinpoints, d'advices et de pointcuts. |
Tisseur ou trammeur | Weaver | Framework pour implémenter des aspects sur le code métier. |
Débogage
Le problème le plus important avec l'AOP est le manque de traçabilité lors du débogage.
Dans la stratégie dynamique, les sauts d'un aspect à un autre peuvent dérouter l'utilisateur non informé.
Tests unitaires en isolation
En Java, on l'appelle JUnit.
C'est un framework de tests unitaires pour les applications Java.
Les annotations permettent de manipuler facilement le scénario d'exécution des tests.
Plusieurs méthodes (assertions) vérifient le comportement du système en fonction de différents résultats.
Annotations JUnit
Les noms des annotations sont explicites :
@Before: Code exécuté avant chaque test.@BeforeClass: Code exécuté avant le premier test et avant@Before.@After: Code exécuté après chaque test.@AfterClass: Code invoqué après l'exécution de tous les tests.
Plusieurs méthodes peuvent être annotées avec
@Beforeou@After.Toutes les méthodes sont invoquées au moment correspondant à leur annotation.
Il n'est pas nécessaire d'invoquer explicitement les méthodes annotées avec
@Beforeet@Afterd'une classe parent.Tant que ces méthodes ne sont pas redéfinies, elles sont automatiquement invoquées lors de l'exécution des tests :
Les méthodes annotées avec
@Beforede la classe parent sont invoquées avant celles de la classe enfant.Les méthodes annotées avec
@Afterde la classe enfant sont invoquées avant celles de la classe parent.
Vérification des résultats
Les méthodes de vérification des résultats font partie de la classe
org.junit.Assert.La plupart de leurs noms commencent par assert.
Elles vérifient si deux instances sont identiques, si une expression est vraie ou nulle.
La seule fonction qui ne respecte pas cette règle de nommage est fail, qui fait échouer le test.
Exemple
Exemple de code
public class ClassToTest {
private int a;
private int b;
public ClassToTest() {
super();
a = b = 0;
}
public ClassToTest(int a, int b) {
super();
this.a = a;
this.b = b;
}
public int add() {
return a + b;
}
public int menus() {
return a - b;
}
}
Exemple de test
package test;
import junit.framework.TestCase;
public class TestClassToTest extends TestCase {
private ClassToTest test;
protected void setUp() throws Exception {
super.setUp();
test = new ClassToTest(3, 4);
}
public void testAdd() {
assertEquals(7, test.add());
// assertEquals("Voluntarily false test for demo", 8, test.add());
}
public void testMenus() {
assertEquals(-1, test.menus());
}
}
Test en isolation
Les tests unitaires isolent chaque composant de l'application pour vérifier son fonctionnement.
Ils sont utiles dans Spring pour vérifier le comportement des méthodes de service.
Ils peuvent également être utilisés pour valider les contrôleurs.
Approche MVC avec Spring MVC
Spring offre une implémentation du modèle MVC via Spring MVC, qui exploite l'injection de dépendances.
Ce module s'abstrait de l'API Java EE Servlet, rendant les informations souhaitées disponibles en tant que paramètres de méthode de contrôleur.
Modèle de conception MVC
L'implémentation du modèle de conception MVC améliore la structure des applications Web en séparant les préoccupations du lancement des processus de la construction de la présentation.
Les frameworks MVC établissent un point d'entrée unique pour diriger les requêtes vers l'entité de traitement appropriée.
Utilisation de MVC
Le modèle MVC est couramment utilisé dans les applications Web et pour les clients lourds afin de présenter des données.
Dans Java EE, il s'appuie généralement sur l'API Servlet et des technologies telles que JSP/JSTL.
Il existe deux types de modèles MVC : le type 1, avec un contrôleur par action, et le type 2, avec un seul contrôleur.
L'accent est mis sur ce dernier, car il est implémenté dans les frameworks MVC.
Structure MVC
Composants clés et leurs interactions au sein du modèle MVC :
Contrôleur frontal : Dirige les requêtes vers l'entité de traitement correcte.
Contrôleur : Traite la requête.
Modèle : Contient les données à présenter.
Vue : Construit la vue avec un pseudo-modèle ou du code Java.
Composants MVC
Caractéristiques des composants utilisés dans ce modèle :
Modèle : Fournit des informations pour la présentation.
Il est indépendant des API techniques et se compose de Java Beans.
Vue : Présente les données du modèle.
Les technologies incluent JSP/JSTL, XML, Velocity, FreeMarker ou de simples classes Java.
Contrôleur : Gère les interactions avec le client et déclenche les processus appropriés.
Il interagit directement avec les composants de la couche de service et récupère les données pour le modèle.
Il utilise un point d'entrée unique pour l'application, dirigeant les processus vers l'entité appropriée.
Le contrôleur frontal est intégré au framework MVC, et seules les entités de traitement sont spécifiques à l'application.
Principes de Spring MVC
Principes clés de Spring MVC :
Utilisation d'un conteneur léger pour configurer les entités MVC et exploiter les fonctionnalités de Spring.
Promotion de la flexibilité et du découplage grâce à la programmation d'interfaces.
Utilisation d'une hiérarchie de contextes d'application pour la séparation logique des composants.
Les composants de service métier n'ont pas accès aux composants MVC.
Caractéristiques des composants MVC
Principales caractéristiques des composants MVC :
À partir de Spring 2.5, la gestion des contrôleurs MVC se fait via des annotations.
Spring MVC masque l'utilisation de l'API Servlet et facilite les tests unitaires à ce niveau.
Gestion des formulaires
La gestion des formulaires utilise des annotations pour charger, afficher et gérer la soumission des formulaires.
Les données sont utilisées pour remplir directement un Bean, qui peut être validé.
Les mécanismes de mappage et de conversion des données sont intégrés et extensibles.
Abstraction
L'abstraction de l'implémentation de la vue des contrôleurs permet de modifier la technologie de présentation sans impacter le contrôleur.
Pour implémenter ces principes et composants, Spring MVC s'appuie sur des entités.
Le traitement des requêtes passe par différentes entités, en commençant par DispatcherServlet et en terminant par la vue choisie.
Traitement des requêtes Spring MVC
DispatcherServlet Il s'agit d'un contrôleur frontal qui reçoit toutes les requêtes HTTP et les délègue à d'autres composants pour le traitement.
Le DispatcherServlet consulte un ou plusieurs HandlerMappings pour trouver le contrôleur approprié pour gérer la requête.
Une fois que le contrôleur a traité la requête, il renvoie généralement un objet ModelAndView.
HandlerMapping : Mappe les requêtes entrantes aux méthodes de gestion.
Il sélectionne le contrôleur approprié en fonction de l'URL de la requête.
Contrôleur Les contrôleurs sont responsables de la gestion des requêtes des utilisateurs et de la préparation du modèle et de la vue à rendre.
ViewResolver : Résout les noms de vue en objets View réels.
View : Rend le modèle dans un format de sortie spécifique (par exemple, HTML, JSON, XML).
Groupes de composants MVC
Les composants Spring MVC peuvent être divisés en trois groupes :
Contrôleur frontal et gestion du contexte d'application : Spécifie les fichiers de contexte et leur chargement ; configure le contrôleur frontal pour spécifier l'accès à l'application.
Gestion du contrôleur : Configure la stratégie d'accès au contrôleur, les classes d'implémentation et les propriétés ; le routage est configuré dans les classes de contrôleur à l'aide d'annotations.
Gestion de la vue : Configure les stratégies de résolution de vue et les frameworks de vue.
Spring / Java EE
Spring est né de l'idée de fournir une solution plus simple et plus légère que Java EE.
Il a été initialement désigné comme un conteneur léger.
L'idée principale est de proposer un framework qui utilise des POJO simples (plain old Java objects) pour développer des applications plutôt que des EJB complexes dans un conteneur.
Spring n'est pas conforme aux spécifications Java EE mais intègre et utilise de nombreuses API Java EE (Servlet, JMS).
Spring offre également une intégration avec certains composants Java EE, y compris les EJB.
Schéma Spring MVC
Spring MVC Gère le flux global de l'application Web.
DispatchServlet : Composant central qui reçoit et achemine les requêtes.
Spring Framework (couche de service) : Contient la logique métier de l'application.
Hibernate/JPA : Gère la persistance des données et les interactions avec la base de données.
Exemples d'injection de dépendances avec Spring
Concept | Rôle | Exemple Spring |
|---|---|---|
IoC/DI | Délègue la gestion des dépendances à Spring |
|
AOP | Gère les préoccupations transversales |
|
MVC | Architecture Web (Modèle-Vue-Contrôleur) |
|
Spring combine ces concepts pour créer des applications modulaires, maintenables et évolutives.
Implémentation
Programmation par contrat
Spring facilite la modification de l'implémentation d'une interface et le passage transparent d'une pseudo-implémentation à l'implémentation réelle une fois terminée.
Développement du code
Approches de développement :
Développement vertical : Un développeur gérant toutes les couches pour une fonctionnalité.
Développement horizontal : Les développeurs se spécialisent dans des couches spécifiques.
Méthodologies de développement
Développement vertical : Les développeurs sont responsables de toutes les couches par Fonction n
Développement horizontal : Fonctions 1, 2, n, par couches (dev 1, dev 2, etc.).
Horizontal - Détails
Nécessite plus de personnes.
Pas toujours possible de définir un partage des tâches aussi clair.
Trouver un compromis entre la productivité et les réalités du projet.
Le développement horizontal améliore :
Pas besoin que les développeurs soient experts dans toutes les technologies.
Plus grande réutilisabilité des services en raison d'une séparation claire des tâches.
Moins de bogues car les programmeurs ne gèrent qu'un seul module et protègent mieux leur code.
Modèle de conception d'usine
Permet à Spring de produire des objets respectant un contrat mais indépendants de leur implémentation.
Basé sur des interfaces et des contrats, avec un point d'entrée unique pour produire des instances d'objets.
Comme une usine produisant différents types de voitures, il produit tout type d'objet respectant le postulat de base.
*Exemple de code :
Schéma d'implémentation
Classe : UsineDeFormulaires
Méthode : +IForm getForm()
Interface : IForm
Méthodes : +IErr validate(), void reset()
Classes implémentant IForm : SwingForm et HTMLForm (toutes deux implémentent validate() et reset())
Comment cela fonctionne-t-il ?
*La modification de getForm() permet de passer d'un formulaire Swing à un formulaire HTML sans impacter le code.
*Spring encourage la programmation par contrat.
*Pendant que SwingForm est en cours de développement, getForm() peut renvoyer une pseudo-implémentation (null ou erreurs codées en dur).
*Ce modèle nécessite des modèles singleton, de configuration et de bean pour être réalisable.
*C'est ainsi que l'inversion de contrôle (IoC) est réalisée.
Modèle Singleton
Garantit qu'une seule instance d'une classe est instanciée dans la machine virtuelle.
Objectifs :
Éviter le temps d'instanciation de la classe.
Éviter la consommation de mémoire inutile.
Contrainte : la classe fournissant le service ne doit pas avoir de notion de session.
Le service doit réagir de la même manière à des paramètres équivalents, quel que soit le module appelant.
Le POJO implémentant le service ne doit pas stocker d'informations au niveau de l'objet.
Ne modifiez pas les variables membres dans une méthode de service !
Étapes d'implémentation
Garantir l'unicité de l'instance en empêchant la création d'instances en dehors du contrôle de la classe.
Rendre le constructeur privé et fournir une méthode qui renvoie une instance de la classe.
Problèmes de multithreading :
Nécessité de gérer les problèmes de multithreading.
Si plusieurs threads accèdent simultanément à getInstance(), les deux pourraient détecter que le membre est nul, ce qui pose un problème.
Déclarer la méthode synchronisée ou la partie du code qui manipule l'instance.
Convention de Bean
Permet à Spring d'effectuer l'injection.
Dans le fichier de configuration, seul le nom de la propriété est connu.
Les propriétés doivent être privées pour maintenir la cohérence du comportement de l'objet.
Pour qu'une classe soit compatible avec la convention JavaBean :
Doit être sérialisable (implémente Serializable).
Doit avoir un constructeur sans argument (constructeur par défaut).
Les propriétés doivent être accessibles via des getters et des setters (set"NomAttribut" et get"NomAttribut").
Description du code