• Aucun résultat trouvé

membres : un tableau de personnes membres du groupe

Utilisateur Modèles

ligne 8 membres : un tableau de personnes membres du groupe

ligne 9 : groupesDeTravail : un dictionnaire affectant une personne à un groupe de travail

On remarquera ici que la classe [GroupePersonnes] ne définit pas de constructeur sans argument. On rappelle qu'en l'absence de tout constructeur, il existe un constructeur "par défaut" qui est le constructeur sans arguments et qui ne fait rien.

On cherche ici, à montrer comment Spring permet d'initialiser des objets complexes tels que des objets possédant des champs de type tableau ou dictionnaire. Le fichier des beans [spring-config-03.xml] de l'exemple 3 est le suivant :

1. <?xml version="1.0" encoding="UTF-8"?>

2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

3. <beans>

4. <bean id="personne1" class="istia.st.springioc03.Personne" init-method="init" destroy-method="close">

5. <property name="nom" value="Simon" />

6. <property name="age" value="40" />

7. </bean>

8. <bean id="personne2" class="istia.st.springioc03.Personne" init-method="init" destroy-method="close">

9. <property name="nom" value="Brigitte" />

10. <property name="age" value="20" />

11. </bean>

12. <bean id="groupe1" class="istia.st.springioc03.GroupePersonnes" init-method="init" destroy-method="close">

13. <property name="membres"> 14. <list> 15. <ref local="personne1" /> 16. <ref local="personne2" /> 17. </list> 18. </property> 19. <property name="groupesDeTravail"> 20. <map>

21. <entry key="Brigitte" value="Marketing" />

22. <entry key="Simon" value="Ressources humaines" />

23. </map>

24. </property>

25. </bean>

26. </beans>

lignes 14-17 : la balise <list> permet d'initialiser un champ de type tableau ou implémentant l'interface List avec différentes valeurs.

lignes 20-23 : la balise <map> permet de faire la même chose avec un champ implémentant l'interface Map. Pour nos tests, nous utiliserons la classe [Main] suivante :

1. package istia.st.springioc03; 2.

3. import org.springframework.beans.factory.xml.XmlBeanFactory; 4. import org.springframework.core.io.ClassPathResource; 5.

6. public class Main { 7.

8. public static void main(String[] args) {

9. // exploitation fichier de configuration spring

10. final XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("spring-config-03.xml"));

11. // récupération du bean [groupe1]

12. GroupePersonnes groupe1 = (GroupePersonnes) bf.getBean("groupe1"); 13. System.out.println("groupe1=" + groupe1.toString());

14. // on supprime les beans

15. bf.destroySingletons();

16. }

17. }

• lignes 12-13 : on demande à spring une référence sur le bean [groupe1] et on affiche la valeur de celui-ci. Les résultats obtenus sont les suivants :

1. init personne [nom=[Simon], age=[40]] 2. init personne [nom=[Brigitte], age=[20]]

3. init GroupePersonnes [membres : [nom=[Simon], age=[40]][nom=[Brigitte], age=[20]], groupes de travail = {Brigitte=Marketing, Simon=Ressources humaines}]

4. groupe1=membres : [nom=[Simon], age=[40]][nom=[Brigitte], age=[20]], groupes de travail = {Brigitte=Marketing, Simon=Ressources humaines}

5. destroy GroupePersonnes [membres : [nom=[Simon], age=[40]][nom=[Brigitte], age=[20]], groupes de travail = {Brigitte=Marketing, Simon=Ressources humaines}]

7. destroy personne [nom=[Brigitte], age=[20]]

Commentaires :

• ligne 12 de [Main], on demande une référence du bean [groupe1]. Spring commence la création de ce bean. Parce que le bean [groupe1] référence les beans [personne1] et [personne2], ces deux beans sont créés (lignes 1 et 2) des résultats. Le bean [groupe1] est ensuite instancié et sa méthode [init] exécutée (ligne 3 des résultats).

• la ligne 13 de [Main] fait afficher la ligne 4 des résultats. • la ligne 15 de [Main] fait afficher les lignes 5-7 des résultats.

15.3 Configuration d'une application n tier avec Spring

Considérons une application 3-tier ayant la structure suivante :

Nous nous proposons de montrer ici l'intérêt de Spring pour construire une telle architecture.

• les trois couches seront rendues indépendantes grâce à l'utilisation d'interfaces Java

• l'intégration des trois couches sera réalisée par Spring La structure de l'application sous Eclipse pourrait être la suivante :

• [1] : la couche [dao] :

• [IDao] : l'interface de la couche

• [Dao1, Dao2] : deux implémentations de cette interface • [2] : la couche [metier] :

• [IMetier] : l'interface de la couche

• [Metier1, Metier2] : deux implémentations de cette interface • [3] : la couche [ui] :

• [IUi] : l'interface de la couche

• [Ui1, Ui2] : deux implémentations de cette interface

• [4] : les fichiers de configuration Spring de l'application. Nous configurerons l'application de deux façons. • [5] : les bibliothèques nécessaires à l'application. Ce sont celles utilisées dans les exemples précédents.

• [6] : le paquetage des tests. [Main1] utilisera la configuration [spring-config-01.xml] et [Main2] la configuration [spring-config-02.xml].

utilisateur Couche interface Couche métier [metier] Couche d'accès aux données [dao] Données utilisateur [ui]

6

5

4

3

2

1

Le but de cet exemple est de montrer que nous pouvons changer l'implémentation d'une ou plusieurs couches de l'application avec un impact zéro sur les autres couches. Tout se passe dans le fichier de configuration de Spring.

La couche [dao]

La couche [dao] implémente l'interface [IDao] suivante : 1. package istia.st.springioc.troistier.dao; 2.

3. public interface IDao {

4. public int doSomethingInDaoLayer(int a, int b);

5. }

L'implémentation [Dao1] sera la suivante :

1. package istia.st.springioc.troistier.dao; 2.

3. public class Dao1 implements IDao { 4.

5. public int doSomethingInDaoLayer(int a, int b) {

6. return a+b;

7. }

8. }

L'implémentation [Dao2] sera la suivante :

1. package istia.st.springioc.troistier.dao; 2.

3. public class Dao2 implements IDao { 4.

5. public int doSomethingInDaoLayer(int a, int b) {

6. return a-b;

7. }

8. }

La couche [métier]

La couche [métier] implémente l'interface [IMetier] suivante : 1. package istia.st.springioc.troistier.metier; 2.

3. public interface IMetier {

4. public int doSomethingInBusinessLayer(int a, int b);

5. }

L'implémentation [Metier1] sera la suivante :

1. package istia.st.springioc.troistier.metier; 2.

3. import istia.st.springioc.troistier.dao.IDao; 4.

5. public class Metier1 implements IMetier { 6.

7. // couche [dao]

8. private IDao dao = null;

9.

10. public IDao getDao() {

11. return dao;

12. }

13.

14. public void setDao(IDao dao) {

15. this.dao = dao;

16. }

17.

18. public int doSomethingInBusinessLayer(int a, int b) {

19. a++; 20. b++; 21. return dao.doSomethingInDaoLayer(a, b); 22. } 23. 24. }

L'implémentation [Metier2] sera la suivante :

1. package istia.st.springioc.troistier.metier; 2.

3. import istia.st.springioc.troistier.dao.IDao; 4.

5. public class Metier2 implements IMetier { 6.

7. // couche [dao]

8. private IDao dao = null;

9.

10. public IDao getDao() {

11. return dao;

12. }

13.

14. public void setDao(IDao dao) {

15. this.dao = dao;

16. }

17.

18. public int doSomethingInBusinessLayer(int a, int b) {

19. a--; 20. b--; 21. return dao.doSomethingInDaoLayer(a, b); 22. } 23. 24. } La couche [ui]

La couche [ui] implémente l'interface [IUi] suivante : 1. package istia.st.springioc.troistier.ui; 2.

3. public interface IUi {

4. public int doSomethingInUiLayer(int a, int b);

5. }

L'implémentation [Ui1] sera la suivante :

1. package istia.st.springioc.troistier.ui; 2.

3. import istia.st.springioc.troistier.metier.IMetier; 4.

5. public class Ui1 implements IUi { 6.

7. // couche [business]

8. private IMetier metier = null;

9.

10. public IMetier getMetier() {

11. return metier;

12. }

13.

14. public void setMetier(IMetier business) {

15. this.metier = business;

16. }

17.

18. public int doSomethingInUiLayer(int a, int b) {

19. a++; 20. b++; 21. return metier.doSomethingInBusinessLayer(a, b); 22. } 23. 24. }

L'implémentation [Ui2] sera la suivante :

1. package istia.st.springioc.troistier.ui; 2.

3. import istia.st.springioc.troistier.metier.IMetier; 4.

5. public class Ui2 implements IUi { 6.

7. // couche [business]

8. private IMetier metier = null;

9.

10. public IMetier getMetier() {

11. return metier;

12. }

13.

14. public void setMetier(IMetier business) {

15. this.metier = business;

16. }

17.

18. public int doSomethingInUiLayer(int a, int b) {

19. a--;

20. b--;

21. return metier.doSomethingInBusinessLayer(a, b);

24. }

Les fichiers de configuration Spring

Le premier [spring-config-01.xml] :

1. <?xml version="1.0" encoding="UTF-8"?>

2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

3. <beans>

4. <!-- la classe dao -->

5. <bean id="dao" class="istia.st.springioc.troistier.dao.Dao1"/>

6. <!-- la classe métier -->

7. <bean id="metier" class="istia.st.springioc.troistier.metier.Metier1">

8. <property name="dao">

9. <ref local="dao" />

10. </property>

11. </bean>

12. <!-- la classe UI -->

13. <bean id="ui" class="istia.st.springioc.troistier.ui.Ui1">

14. <property name="metier"> 15. <ref local="metier" /> 16. </property> 17. </bean> 18. </beans> Le second [spring-config-02.xml] : 1. <?xml version="1.0" encoding="UTF-8"?>

2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

3. <beans>

4. <!-- la classe dao -->

5. <bean id="dao" class="istia.st.springioc.troistier.dao.Dao2"/>

6. <!-- la classe métier --> 7. <bean id="metier" 8. class="istia.st.springioc.troistier.metier.Metier2"> 9. <property name="dao"> 10. <ref local="dao" /> 11. </property> 12. </bean> 13. <!-- la classe UI -->

14. <bean id="ui" class="istia.st.springioc.troistier.ui.Ui2">

15. <property name="metier">

16. <ref local="metier" />

17. </property>

18. </bean>

19. </beans> Les programmes de test

Le programme [Main1] est le suivant :

1. package istia.st.springioc.troistier.main; 2. 3. import org.springframework.beans.factory.xml.XmlBeanFactory; 4. import org.springframework.core.io.ClassPathResource; 5. 6. import istia.st.springioc.troistier.ui.IUi; 7.

8. public class Main1 { 9.

10. public static void main(String[] args) {

11. // on récupère une implémentation de l'interface IUi

12. IUi ui = (IUi) (new XmlBeanFactory(new ClassPathResource("spring-config-01.xml"))).getBean("ui"); 13. // on utilise la classe

14. int a = 10, b = 20;

15. int res = ui.doSomethingInUiLayer(a, b); 16. // on affiche le résultat

17. System.out.println("ui(" + a + "," + b + ")=" + res); 18. }

19. 20. }

Le programme [Main1] utilise le fichier de configuration [spring-config-01.xml] et donc les implémentations [Ui1, Metier1, Dao1] des couches. Les résultats obtenus sur la console Eclipse :

ui(10,20)=34

Le programme [Main2] est le suivant :

1. package istia.st.springioc.troistier.main; 2. 3. import org.springframework.beans.factory.xml.XmlBeanFactory; 4. import org.springframework.core.io.ClassPathResource; 5. 6. import istia.st.springioc.troistier.ui.IUi; 7.

10. public static void main(String[] args) {

11. // on récupère une implémentation de l'interface IUi

12. IUi ui = (IUi) (new XmlBeanFactory(new ClassPathResource("spring-config-02.xml"))).getBean("ui"); 13. // on utilise la classe

14. int a = 10, b = 20;

15. int res = ui.doSomethingInUiLayer(a, b); 16. // on affiche le résultat

17. System.out.println("ui(" + a + "," + b + ")=" + res); 18. }

19. 20. }

Le programme [Main2] utilise le fichier de configuration [spring-config-02.xml] et donc les implémentations [Ui2, Metier2, Dao2] des couches. Les résultats obtenus sur la console Eclipse :

ui(10,20)=-10

15.4 Conclusion

L'application que nous avons construite possède une grande souplesse d'évolution. On y change l'implémentation d'une couche par simple configuration. Le code des autres couches reste inchangé. Ceci est obtenu grâce au concept IoC qui est l'un des deux piliers de Spring. L'autre pilier est AOP (Aspect Oriented Programming) que nous n'avons pas présenté. Il permet d'ajouter, également par configuration, du "comportement" à une méthode de classe sans modifier le code de celle-ci.

16 Application web MVC dans une architecture 3tier – Exemple 2