Aujourd'hui, avec Spring Boot, la promesse est de pouvoir bootstrapper en 60 secondes chrono une application.
C'est génial et porteur de sens (et un vrai laboratoire de bonnes pratiques) mais le temps de bootstrapping de l'équipe de développement, des individus composant cette équipe, est bien loin de suivre la même célérité. Dans le pire des cas, vous rencontrerez même des équipes au sein desquelles les écarts de niveaux sont extrêmement importants.
Pourquoi donc ? Réfléchissez à ce qui se passe si vous donnez le volant d'une formule 1 à quelqu'un qui vient tout juste d'obtenir son permis A après avoir fait son apprentissage sur une petite citadine dans une grande ville ... et vous aurez un début de réponse.
Le portfolio Spring constitue une excellente et populaire boîte à outils qui vous promet une grande productivité. Pour tirer profit de cette productivité et ne pas rester bridé par les connaissances de l'équipe, il ne suffit pas de choisir le bon framework, il faut savoir comment l'utiliser, le sublimer, en épousant les paradigmes de ce dernier.
Je vous propose donc d'en revenir aux fondamentaux de Spring (Boot) afin de vous permettre, bien avant de pouvoir vous attaquer au graal des architectures Microservices, d'être capable de tirer la pleine puissance du framework, tout du moins de ne pas en détourner l'essence.
Si vous n'êtes pas familier de Spring, ce talk vous permettra d'en avoir un premier aperçu pragmatique sans effet waouh. Si vous connaissez déjà Spring, vous trouverez à travers ce talk l'opportunité de prendre du recul sur son usage et de confronter vos pratiques aux patterns et bénéficies qu'il vous offre.
[BreizhCamp 2016] La relecture de code : avant tout des pratiques
Spring Meetup Paris - Back to the basics of Spring (Boot)
1. Spring Meetup - @esiber @interface21_ug
Back to the basics of Spring (Boot)
Développement d’applications
Java avec Spring
1
Reprenons et renforçons les fondamentaux
Soirée Spring Meetup Paris - 27/02/2019
2. Spring Meetup - @esiber @interface21_ug
Faisons connaissance
2
➢ Agile Java Craftsman freelance
○ Senior Software Craftsman
○ Coach agile / technique
○ Formateur
○ Management technique et agile
○ Audit et conseil (technique et organisationnel)
➢ Expert Spring
○ Développeur sur l’écosystème depuis 2008
○ SpringSource Certified Spring Professional & Certified Enterprise Integration Specialist
○ Animation de formations en intra- / inter-entreprise
➢ Repères et contacts
○ https://eric.siber.fr/
○ eric@agiledev.tech
3. Spring Meetup - @esiber @interface21_ug
Faisons connaissance
3
➢ Qui êtes vous ?
➢ De quoi (ne) va-t-on (pas) parler ?
➢ Mettre en pratique ?
4. Spring Meetup - @esiber @interface21_ug
Quelles sont les dernières versions ?
4
➢ Spring Framework 5.1.5.RELEASE
➢ Spring Security 5.1.4.RELEASE
➢ Spring Boot 2.1.3.RELEASE
➢ Spring Tool Suite 3.9.7.RELEASE
➢ Spring Tools 4.1.2.RELEASE
6. Spring Meetup - @esiber @interface21_ug
La genèse de Spring Framework
Publication en 2002 par Rod Johnson
● "J2EE Myths"
● "The return on investment in many J2EE projects is disappointing"
● Contient 30 000 LOC du futur Spring Framework pour illustrer le propos
Sortie de Spring Framework 0.9 en licence Open Source en juin 2003
Création de la société Interface21
6
7. Spring Meetup - @esiber @interface21_ug
De la société Interface21 à Pivotal
Organisationnel
● Juin 2003 : Interface21
● Mai 2007 : Levée de 10 M$
● Novembre 2007 : Interface21 devient
SpringSource
● Juin 2008 : Levée de 27 M$
● Août 2009 : VMWare rachète SpringSource
pour 420 M$
● Juillet 2012 : Rod Johnson quitte SpringSource
● Avril 2013 : une Joint Venture entre VMWare et
sa maison mère EMC donne la création de
Pivotal
● Octobre 2013 : http://springsource.org devient
http://spring.io
7
Technique
● Mars 2004 : Spring Framework 1.0
● Octobre 2006 : Spring Framework 2.0
● Novembre 2007 : Spring Framework 2.5
● Décembre 2009 : Spring Framework 3.0
● Avril 2011 : Spring Data 1.0
● Décembre 2013 : Spring Framework 4.0 + annonce de
Spring IO et premières références à ce qui deviendra
Spring Boot
● Avril 2014 : Spring Boot 1.0
● Mars 2015 : Spring Cloud 1.0
● Septembre 2017 : Spring Framework 5.0 avec support de
Java 9 (sorti 7 jours avant) et JUnit 5
● Mars 2018 : Spring Boot 2.0
● Juin 2018 : Spring Cloud 2.0
8. Spring Meetup - @esiber @interface21_ug
Où met-on les pieds ? Kit de survie
8
9. Spring Meetup - @esiber @interface21_ug
Fonctions de base remplies par Spring
Spring est un conteneur léger (en opposition aux serveurs d’application Java
EE) se présentant comme un framework multi-couches proposant :
9
➢ Une implémentation du Design Pattern Inversion of Control se
matérialisant par une Fabrique et la déclaration de composants (beans)
➢ Un support de la Programmation Orientée Aspects (AOP)
➢ Un couche d’abstraction permet d’intégrer / simplifier l’usage d’autres
frameworks (ex. JDBC)
10. Spring Meetup - @esiber @interface21_ug
Aperçu général du portfolio Spring (1/2)
10
Fonctions de base
11. Spring Meetup - @esiber @interface21_ug
Aperçu général du portfolio Spring (2/2)
11
Source
Spring Framework
Runtime
12. Spring Meetup - @esiber @interface21_ug
Outillage préconisé pour Spring
12
Spring Tools
Spring Tools 3 (ex. STS)
13. Spring Meetup - @esiber @interface21_ug
Outillage compatible/supporté par Spring
13
➢ La majorité du portfolio Spring est construit avec Gradle depuis 2012
(précédemment Maven était employé)
➢ Tous les guides proposent les éléments de configuration pour les 2 outils
14. Spring Meetup - @esiber @interface21_ug
Concepts clés à appréhender
14
15. Spring Meetup - @esiber @interface21_ug
Design Pattern Factory (Fabrique)
La Factory consiste déléguer à un tiers la responsabilité de fabrication des
instances de certains objets.
Ce pattern a pris son essor avec l’usage de la programmation par interfaces
Variante : Abstract Factory
15
16. Spring Meetup - @esiber @interface21_ug
Approche orientée composants et POJOs
Plain Old Java Object fait référence à la simplicité d’une classe Java héritant
de la classe Object, en opposition à des classes liées explicitement à une
infrastructure par héritage ou implémentation (ex. EJB 2.1)
Egalement appelé JavaBeans
Constitution :
➢ Attributs
➢ Getters
➢ Setters
16
17. Spring Meetup - @esiber @interface21_ug
Inversion de contrôle
IoC = Inversion of Control
17
Principe à Hollywood : « Don’t Call Us, We’ll Call You! »
L’objet ne prend plus la responsabilité ni de se créer, ni de se rattacher les
autres objets dont il a besoin
18. Spring Meetup - @esiber @interface21_ug
Injection de dépendances
DI = Dependency Injection
18
Elle consiste à rattacher à un objet les autres objets dont il a besoin en dehors
du processus d’instanciation / initialisation de l’objet
La DI peut donc être considérée comme un sous-ensemble de l’IoC
L’implémentation de ce pattern est fortement liée à la mise en place d’une
fabrique
➢ La fabrique Spring va au delà de la DI et supporte l’IoC
19. Spring Meetup - @esiber @interface21_ug
Concepts clés en action
19
20. Spring Meetup - @esiber @interface21_ug
Préambule sur la déclaration d’un bean Spring
Spring propose (au moins) 3 modes de déclarations pour sa fabrique
➢ Par XML
➢ Par annotations … introduit dans Spring Framework 2.5
➢ Par déclarations en Java (Java Config) … introduit dans Spring Framework 4.0 et
arrivé à maturation dans Spring Framework 4.0 après incubation dans le projet
Spring JavaConfig évoqué pour la première fois en 2007
20
Pourquoi au moins 3 ?
➢ API interne (prudence)
➢ Groovy Configuration
➢ Incubation de DSLs orientés programmation fonctionnelle en Kotlin et Java dans le
projet Spring Fu
➢ Etc. ?
21. Spring Meetup - @esiber @interface21_ug
Déclaration d’un bean Spring en XML
➢ Fonctionnalité historique
➢ Syntaxe permettant de déclarer des composants et leurs caractéristiques
➢ Repose sur le principe de POJO, en particulier la présence de setters
21
22. Spring Meetup - @esiber @interface21_ug
Déclaration d’un bean Spring en XML
Initialisation d’une caractéristique :
22
Déclaration du composant :
Initialisation d’une caractéristique par le constructeur :
23. Spring Meetup - @esiber @interface21_ug
Déclaration d’un bean Spring en XML
Quelques attributs de la balise <bean /> à connaître / explorer :
➢ name
➢ init-method
➢ abstract
➢ parent
➢ scope
➢ primary
➢ …
23
Ainsi qu’une balise complémentaire :
24. Spring Meetup - @esiber @interface21_ug
Injection de dépendances full XML
Assemblage de composants
24
Dépendance anonyme
25. Spring Meetup - @esiber @interface21_ug
L’injection de dépendances dans tous ses états
25
3 stratégies d’injection :
➢ par constructeur : pour les dépendances obligatoires
➢ par setter : pour les dépendances facultatives
➢ par champs : à éviter / ne réserver qu’aux tests
Assemblage demandé à la fabrique sur la base :
➢ d’un nom (id / name / alias)
➢ d’un type (classe)
Pourquoi vous devriez arrêter d’utiliser les fields injection
26. Spring Meetup - @esiber @interface21_ug
Démarrage d’une application Spring
Objectif : Création du conteneur / de la fabrique Spring (ApplicationContext)
➢ Rendre disponible le fichier XML de configuration dans le classpath
➢ Utiliser la classe o.s.context.support.ClassPathXmlApplicationContext
26
Méthodes pour interagir avec la fabrique
➢ boolean containsBean(String name)
➢ Object getBean(String name)
➢ T getBean(Class <?> requiredType)
➢ Map<String, T> getBeansOfType(Class <?> type)
➢ ...
27. Spring Meetup - @esiber @interface21_ug
Focus sur les dépendances concernées
27
28. Spring Meetup - @esiber @interface21_ug
Focus sur les dépendances concernées
28
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
29. Spring Meetup - @esiber @interface21_ug
Fonctionnement d’un conteneur Spring
29
30. Spring Meetup - @esiber @interface21_ug
Cycle de vie des beans Spring
Les différentes étapes par
lesquelles passe la fabrique :
● à sa création
● à sa destruction
30
Interfaces significatives :
● ApplicationContextAware
● BeanPostProcessor
● InitializingBean
● DisposableBean
● (BeanFactoryPostProcessor)
31. Spring Meetup - @esiber @interface21_ug
Cycle de vie des beans Spring - ex. simplifié
● Chargement des définitions
● Instanciation (inclut l’injection
par constructeur)
● Appel des setters / assemblage
● Appel de la méthode
afterPropertiesSet()
● Appel de la méthode
d’initialisation
31
32. Spring Meetup - @esiber @interface21_ug
Cycle de vie - les post-processeurs
Objectif : greffer un traitement particulier dans le cycle de vie de chargement /
initialisation de la fabrique
➢ Un BeanFactoryPostProcessor est appelé après chargement en
mémoire des définitions d’une fabrique
❏ Permet d’appliquer un traitement sur la fabrique avant instanciation
des composants
❏ Ex. o.s.b.factory.config.PropertySourcesPlaceholderConfigurer
➢ Un BeanPostProcessor permet d’exécuter un traitement sur un bean
donné avant / après l’exécution d’éventuelles méthodes d’initialisation
32
33. Spring Meetup - @esiber @interface21_ug
Notion de scopes
Le scope est la portée d’un composant Spring vivant en mémoire
Les principaux scopes sont :
➢ prototype : une instance différente est systématiquement fournie par la fabrique
➢ singleton : une instance unique (scope par défaut)
➢ request : une instance unique attaché à une requête HTTP
➢ session : une instance unique attaché à une session HTTP
Fonction du scope associé à la définition d’un composant, la fabrique décide
lorsqu’elle est appelée - et fonction du contexte d’appel - si elle recycle une
instance existante ou en crée une autre
33
34. Spring Meetup - @esiber @interface21_ug
Création de composants avec un FactoryBean
org.springframework.beans.factory.FactoryBean est une interface
permettant de définir une fabrique spécifique à confier au conteneur Spring
34
Utile lorsque l’initialisation du composant dépend d’éléments externes à
l’application (ex. récupération d’une URL depuis un WebService ou depuis la
base de données)
35. Spring Meetup - @esiber @interface21_ug
Injection de la fabrique dans un bean
org.springframework.context.ApplicationContextAware est une interface
permettant de définir une fabrique spécifique à confier au conteneur Spring
35
La méthode de callback void setApplicationContext(ApplicationContext
applicationContext) est appelée dans le cycle d’initialisation de la
fabrique.
36. Spring Meetup - @esiber @interface21_ug
Configuration Spring en XML
36
37. Spring Meetup - @esiber @interface21_ug
Externalisation de paramètres
Le besoin
➢ Souvent, le fichier de configuration XML est mis dans le classpath, plus
précisément packagé avec le code dans un JAR (qu’on appellera “le
binaire”. La modification d’une propriété implique donc “modification du
binaire”
➢ Des éléments de configuration peuvent également varier selon
l’environnement de déploiement (DEV, REC, PROD) et on ne souhaitera
pas fabriquer un binaire spécifique à chaque environnement
➢ Plus l’application est grande, plus les définitions de composants se
multiplient, ce qui rend difficile le changement d’une propriété
37
38. Spring Meetup - @esiber @interface21_ug
Externalisation de paramètres
Solution : o.s.context.support.PropertySourcesPlaceholderConfigurer
➢ Introduit avec Spring 3.1
➢ Précédemment o.s.b.factory.config.PropertyPlaceholderConfigurer
38
➢ Repose sur une syntaxe ${...} appelée placeholders pour associer à une
propriété d’un bean une référence (la clé) à une données externalisée
dans un fichier (clé=valeur)
39. Spring Meetup - @esiber @interface21_ug
Les namespaces (1/3)
En XML, un namespace est un espace de nom définissant une grammaire. Il
est associé à un descripteur XSD (XML Schema Definition)
Un fichier XML Spring dispose par défaut du namespace bean lequel définit
toutes les balises / attributs utilisables au sein de la racine <beans>
39
Ce n’est pas le seul, Spring 2.0 a introduit d’autres namespaces et la
possibilité de définir ses propres namespaces.
40. Spring Meetup - @esiber @interface21_ug
Deux catégories de namespaces
➢ Simplification / allègement de la syntaxe d’un bean Spring
○ Le namespace p
○ Le namespace c
➢ Approche composant pour simplifier / masquer une à plusieurs
déclaration reposant sur un modèle POJO
○ Le namespace util
○ Le namespace context
Les namespaces (2/3)
40
Support dans STS
41. Spring Meetup - @esiber @interface21_ug
Les namespaces (3/3)
41
Exemple de bénéfices
<property name="props">
<props>
<prop key="mail.smtp.host">localhost</prop>
<prop key="mail.smtp.port">2525</prop>
</props>
</property>
<property name="props">
<util:properties location="mail.properties"
/>
</property>
42. Spring Meetup - @esiber @interface21_ug
Découpage et assemblage de configurations Spring
A l’image de la séparation en couches dans une architecture n-tiers
Permet de séparer en domaines métiers / couches techniques
Facilite les ajustements sur un contexte spécifique à des tests
Syntaxe pour inclure un fichier dans un autre
Possibilité d’utilisation le joker * dans le nom de la ressource à inclure
42
43. Spring Meetup - @esiber @interface21_ug
Notion de profils
L’externalisation de propriétés trouve ses limites face au besoin de non pas
configurer différemment un composant, mais d’utiliser un autre
composant (d’une autre implémentation dans le cas d’une programmation
par interface)
Les profils répondent à ce besoin en permettant de déclarer plusieurs
alternatives à un bean nommé (id) et de faire l’association de chaque
alternative à une définition d’environnement
43
44. Spring Meetup - @esiber @interface21_ug
Arrête de nous bassiner avec ton XML
44
45. Spring Meetup - @esiber @interface21_ug
Déclarations et injections par annotations (1/4)
Consiste à déclarer des beans Spring grâce à l’usage des annotations
Comporte également un support pour l’injection de dépendances par
l’usage d’annotations
Sa prise en charge au niveau de la fabrique Spring passe par une déclaration
XML (namespace context)
45
46. Spring Meetup - @esiber @interface21_ug
Déclarations et injections par annotations (2/4)
Déclaration d’un bean Spring en annotant le POJO avec
org.springframework.stereotype.Component
Il existe d’autres annotations plus spécialisées en lien avec un type de
composant :
➢ org.springframework.stereotype.Repository
➢ org.springframework.stereotype.Service
Convention de nommage du bean en l’absence de valeur passé à l’annotation
46
47. Spring Meetup - @esiber @interface21_ug
Déclarations et injections par annotations (3/4)
Le paramétrage XML d’un bean Spring trouve un équivalent à travers
l’annotation org.springframework.beans.factory.annotation.Value
L’injection de dépendances sur un bean Spring trouve un équivalent à travers
l’annotation org.springframework.beans.factory.annotation.Autowired
47
Stratégie de résolution d’une dépendance basée sur l’ordre suivant :
➢ Correspondance sur le type (classe)
➢ Correspondance sur le @Qualifier (nom et/ou catégorisation de bean)
➢ Correspondance entre le nom du paramètre et le nom du bean injecté
48. Spring Meetup - @esiber @interface21_ug
Déclarations et injections par annotations (4/4)
48
Rappel : les 3 modes d’injection (Field, Property/Setter, Constructor) s’appliquent
pour la déclaration / injection (ainsi que les bonnes pratiques déjà évoquées)
Injection par Field
49. Spring Meetup - @esiber @interface21_ug
Déclarations en Java Config (1/4)
Consiste à déclarer des beans Spring via des classes / méthodes Java
Écart à une approche de l’IoC reposant à 100% sur une Factory avec le retour
de l’instanciation d’objets qui restent néanmoins intégrés au conteneur
Repose sur l’usage d’annotations et le modèle d’injection de dépendances
par annotation
49
50. Spring Meetup - @esiber @interface21_ug
Déclarations en Java Config (2/4)
50
L’identification d’une classe de configuration s’appuie sur l’usage de
l’annotation org.springframework.context.annotation.Configuration
La déclaration d’un bean Spring se fait par l’usage de l’annotation
org.springframework.context.annotation.Bean sur une méthode renvoyant
l’instance
Les paramètres d’une méthode annotée @Bean seront résolus par appel de la
fabrique Spring
51. Spring Meetup - @esiber @interface21_ug
Déclarations en Java Config (3/4)
51
52. Spring Meetup - @esiber @interface21_ug
Déclarations en Java Config (4/4)
Hors usage de Spring Boot (et de sa magie / ses conventions), sa prise en
charge au niveau de la fabrique Spring passe par le même type de déclaration
XML (namespace context) que celui illustré pour la déclaration par
annotations.
En effet, l’annotation @Configuration fait de la classe annotée aussi un bean
Spring, rendant possible notamment les mécanismes d’injection (cf.
@Autowired)
52
53. Spring Meetup - @esiber @interface21_ug
Spring et le standard Java EE
53
54. Spring Meetup - @esiber @interface21_ug
Spring comme source d’inspiration
54
Source
55. Spring Meetup - @esiber @interface21_ug
Effort de normalisation
55
Source
Apparition d’éléments
apparentés à ceux connus
avec Spring :
➢ beans.xml
➢ @Inject
➢ @Named
➢ ...
56. Spring Meetup - @esiber @interface21_ug
Deux mondes en opposition ?
56
➢ Certaines annotations Java EE
sont supportées par Spring
➢ Plus de détails sur cette
présentation datant de 2015
(n’incluant pas Spring Boot)
57. Spring Meetup - @esiber @interface21_ug
Deux mondes en opposition ?
57
Source
58. Spring Meetup - @esiber @interface21_ug
Deux mondes en opposition ?
58
Source (publication de novembre 2018)
59. Spring Meetup - @esiber @interface21_ug
Parts de marché sur les solutions Web Java
59
Source
60. Spring Meetup - @esiber @interface21_ug
Tendances façon mercato
60
Source étude octobre 2016
61. Spring Meetup - @esiber @interface21_ug
Spring et les pratiques de tests
61
62. Spring Meetup - @esiber @interface21_ug
Bénéfices immédiats pour l’écriture de tests unitaires
L’approche de programmation par interface, ainsi que le recours à des POJOs
apporte une structure propice à l’écriture de tests unitaires (TU) :
● pas d’adhérence technique explicite (héritage)
● faible couplage grâce à l’injection de dépendances
● facilité de mise en oeuvre de bouchons et autres substituts / simulacres
Le conteneur Spring n’intervient simplement pas dans le cas de TU et vous
pouvez donc recourir à vos frameworks / librairies préféré(e)s en instancier /
configurer vous même l’objet testé
62
63. Spring Meetup - @esiber @interface21_ug
Spring Test et isolation d’un lot de composants
Le module Spring Test, aussi appelé Spring TestContext Framework, propose
une prise en charge des frameworks / librairies de test les plus populaires.
Il propose notamment une infrastructure pour faciliter l’intégration avec JUnit et
TestNG, ainsi que Mockito.
63
64. Spring Meetup - @esiber @interface21_ug
Tests d’intégration - un premier aperçu
Objectif : permettre à un test JUnit 4.12 de requêter la fabrique Spring
➢ org.springframework.test.context.junit4.SpringRunner pour lancer
➢ org.springframework.test.context.ContextConfiguration pour configurer
64
65. Spring Meetup - @esiber @interface21_ug
Cycle de vie d’un test JUnit géré par Spring (1/2)
Spring Test apporte la plomberie nécessaire pour s’intégrer au cycle de vie
d’exécution de test propre à JUnit
➢ Dans le cas de JUnit 4.x, Spring Test apporte une implémentation compatible avec l’annotation
@RunWith : org.springframework.test.context.junit4.SpringRunner (alias de
SpringJUnit4ClassRunner)
➢ Le prérequis en matière de version est JUnit 4.12 à compter de Spring Framework 4.3
➢ Un support de JUnit 5 est disponible depuis Spring Framework 5.0
Recourir au conteneur Spring dans un test est synonyme d’écriture d’un test
d’intégration (qu’elle que soit la profondeur de ce dernier), combiné ou non
avec une stratégie d’isolation reposant sur l’usage de mocks.
65
66. Spring Meetup - @esiber @interface21_ug
Cycle de vie d’un test JUnit géré par Spring (2/2)
En plus du support du fonctionnement standard (illustré par les annotations
@BeforeAll, @Before, @After, @AfterAll pour JUnit 4.x), Spring Test greffe
sur le cycle de vie une étape d’initialisation / destruction de contexte Spring
(fabrique) via l’usage de l’annotation @ContextConfiguration
➢ Le création (destruction) du contexte Spring de test précède (succède à) l’exécution des étapes
schématisées par l’annotation @BeforeAll (@AfterAll).
➢ Spring Test optimise même cette étape en recyclant le contexte commun à plusieurs classes de
test, ce qui permet un gain de performance dans l’exécution d’une batterie de tests
➢ Beaucoup d’autres fonctionnalités plus avancées existent pour tuner le cycle de vie /
d’exécution d’une classe de test (à commencer par l’annotation DirtiesContext)
66
67. Spring Meetup - @esiber @interface21_ug
Tests d’intégration avec Spring (et JUnit 4.x)
L’infrastructure Spring Test mise en place pour piloter un test d’intégration (TI)
avec JUnit 4.x :
➢ supporte les configurations XML et Java Config
➢ peut nécessiter découpage / assemblage spécifique d’un contexte Spring
➢ supporte l’utilisation de l’injection de dépendances (injection par champs
préconisé) via @Autowired
67
Schématisation d’un TI sur 3 couches avec recours
à une base de données spécifique aux tests
68. Spring Meetup - @esiber @interface21_ug
La programmation orientée aspect (AOP) avec
Spring
68
69. Spring Meetup - @esiber @interface21_ug
Notions de préoccupations transverses (1/2)
Malgré une architecture en couches, on constate souvent que des concepts
transverses se matérialisent dans une classe donnée (hors objets du domaine)
et viennent en quelque sorte envahir celle-ci et créer du bruit :
● la fonction première de la classe ressort moins
● le code ajouté se ressemble de classes en classes
● la testabilité de la classe peut en pâtir
Ces préoccupations transverses sont aussi appelée Aspects
69
ex. EventService
70. Spring Meetup - @esiber @interface21_ug
Notions de préoccupations transverses (2/2)
Exemples :
● la sécurité
● le monitoring
● la gestion des erreurs
● le caching
● la gestion transactionnelle
● ….
70
L’AOP (Aspect Oriented Programming) vient apporter une réponse à cette
problématique
71. Spring Meetup - @esiber @interface21_ug
Concepts et vocabulaire
JoinPoint : étape d'exécution sur laquelle un complément est susceptible d’
être apporté
PointCut : formulation sous forme d’expression qualifiant un JoinPoint
Advice : désigne l’action particulière réalisée sur un JoinPoint
Target object : l’objet cible qu’on cherche à enrichir
Weaving : l’action de greffer le code d’un aspect dans l’objet cible (en français
on parle de “tissage des aspects”)
71
72. Spring Meetup - @esiber @interface21_ug
Les différents types d’advices rencontrés avec
Spring➢ Before : avant le code ciblé
➢ After returning : à l’issue de l’exécution du code ciblé (sauf cas de
déclenchement d’erreur)
➢ After throwing : à l’issue du déclenchement d’une erreur interrompant
l’exécution du code ciblé
➢ After (finally) : à l’issue de l’exécution du code ciblé, quelque soit le
comportement rencontré
➢ Around : autour du code ciblé (avant et après, avec la possibilité de
bloquer l’exécution du code ciblé)
72
73. Spring Meetup - @esiber @interface21_ug
Les approches proposées par Spring
Spring propose deux approches de programmation :
● une approche XML reposant sur l’utilisation exclusive du namespace aop
● une approche par l’usage d’annotation, appelée @AspectJ annotation style
Elles exploitent toutes les deux le langage AspectJ pour désigner les PointCut
73
Spring peut mettre en oeuvre l’AOP de deux façons :
➢ Spring AOP
➢ AspectJ
74. Spring Meetup - @esiber @interface21_ug
Spring AOP (1/3)
Spring AOP se charge de tisser les aspects à l’exécution (Runtime)
Il s’appuie sur deux solutions fonction de la situation :
➢ Le Design Pattern Proxy et l’API Dynamic Proxy présente dans le JDK
➢ La librairie CGLib pour instrumenter le code (abus de langage) le bytecode
74
Les 2 cas de figure sont :
➢ Couple interface / implémentation
➢ Absence de contrat d’interface
75. Spring Meetup - @esiber @interface21_ug
Spring AOP (2/3)
Zoom sur le Design Pattern Proxy avec un exemple :
75
● Bean EventJdbcRepository
implémentant l’interface EventRepository
● Bean EventService ayant une
dépendance de type EventRepository
76. Spring Meetup - @esiber @interface21_ug
Spring AOP (3/3)
76
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
...
</aop:aspect>
</aop:config>
<bean id="aBean" class="org.comp.app.MyBean">
...
</bean>
<aop:pointcut id="bsService"
expression="execution(* org.comp.app.service.*.*(..))"
/>
<aop:before pointcut-ref="bsService"
method="monitor"/>
Exemple XML based :
La méthode monitor() se situe
dans ... MyBean
77. Spring Meetup - @esiber @interface21_ug
AspectJ (1/2)
AspectJ c’est :
➢ Un langage
➢ Une API
Dans le cadre de Spring, c’est de son intégration à ce dernier qu’il s’agit :
➢ La configuration d’un aspect ne peut se faire qu’avec le modèle déclaratif par annotations.
➢ AspectJ va tisser les aspects dès le build
Pour cela, il sera requis d’ajouter la dépendance aspectjweaver.jar sans quoi le
tissage ne se fera pas.
77
78. Spring Meetup - @esiber @interface21_ug
AspectJ (2/2)
La couverture fonctionnelle
d’AspectJ est bien plus importante
que celle de Spring AOP
78
La documentation Spring Framework est claire sur ce point : Spring AOP ne
se place pas en compétiteur d’AspectJ
Source
L’activation dans Spring du support des APIs AspectJ passe (dans le cas d’une
déclaration XML) par l’ajout suivant :
<aop:aspectj-autoproxy />
79. Spring Meetup - @esiber @interface21_ug
Spring AOP & AspectJ - en synthèse
➢ Deux solutions techniques
○ Spring AOP au Runtime
○ AspectJ au Build
➢ Deux styles de déclaration pour Spring AOP
○ XML
○ Annotation
➢ Un langage (AspectJ) commun pour exprimer les PointCuts
➢ Un choix à peser entre les deux solutions
○ Spring AOP ne pourra cibler que des beans Spring
○ AspectJ peut cibler n’importe quel objet et a une couverture fonctionnelle plus complète
en matière de JoinPoint
79
80. Spring Meetup - @esiber @interface21_ug
Tout ça pour quoi ?
80
81. Spring Meetup - @esiber @interface21_ug
Exemple de mise en oeuvre de l’AOP avec le
support de l’asynchronicité
L’asynchronicité est un exemple de préoccupation transverse pour lequel
Spring propose un support “out of the box”
➢ Namespace task : <task:annotation-driven />
➢ Annotation @Async à appliquer sur une méthode
81
82. Spring Meetup - @esiber @interface21_ug
Principal piège lors de l’usage de Spring AOP
82
@Async
public void informNewEventCreation(List<Subscriber> subscribers, Event event) {
Session session = getSession();
for (Subscriber subscriber : subscribers) {
try {
informNewEventCreation(session, subscriber, event);
} catch (MessagingException e) {
LOGGER.error("An error occurred");
}
}
}
@Async
private void informNewEventCreation(Session session, Subscriber s, Event e) throws MessagingException {
// sending an email
}
84. Spring Meetup - @esiber @interface21_ug 84
Qu’apporte Spring Boot ?
84
Spring Boot c’est :
➢ Démarrage rapide du développement d’un projet Spring
➢ Simplification de la gestion des dépendances
➢ Activation automatique de certaines configurations
➢ Activation d’un nombre conséquent de fonctionnalités par défaut
Spring est un formidable outil de développement d’applications … mais sa
configuration peut être lourde, compliquée et chronophage.
85. Spring Meetup - @esiber @interface21_ug 8585
Qu’apporte Spring Boot ?
86. Spring Meetup - @esiber @interface21_ug 8686
Bootstrapping avec Spring Initializr (1/2)
https://start.spring.io/
➔ Générer
➔ Dézipper
➔ Importer
➔ Démarrer
87. Spring Meetup - @esiber @interface21_ug 8787
Bootstrapping avec Spring Initializr (2/2)
88. Spring Meetup - @esiber @interface21_ug 8888
Ajout de fonctionnalités - les starters (1/3)
Le choix des ingrédients
➢ Avec une granularité moins fine (orientée “besoin” et non solution)
➢ Avec une compatibilité des différents ingrédients entre eux gérée par
Spring Boot
➢ … y compris pour les dépendances externes à Spring Framework
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
89. Spring Meetup - @esiber @interface21_ug 8989
Ajout de fonctionnalités - les starters (2/3)
Avec Maven, Spring Boot peut s’intégrer sous 2 formes grâce au
spring-boot-starter-parent
➢ Via la notion de pom parent
➢ Via l’import de la dépendance
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
Ce parent fixe toutes les versions de modules Spring et librairies externes
amies via des property dans Maven
90. Spring Meetup - @esiber @interface21_ug 9090
Ajout de fonctionnalités - les starters (3/3)
Spring Boot propose également un plugin Maven afin de configurer le
build (en particulier le livrable) et permettre un démarrage avec Maven
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
91. Spring Meetup - @esiber @interface21_ug 9191
Optimisation de la productivité du développeur
Un starter particulier dédié au développement : les DevTools
Attention : ces fonctionnalités ne sont pas destinées à la production
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
92. Spring Meetup - @esiber @interface21_ug 9292
Optimisation de la productivité du développeur
Key feature des DevTools : le rechargement à chaud du contexte
➢ au moindre changement (enregistrement) détecté par l’IDE
➢ possibilité de tuner le mécanisme
➢ possibilité de désactiver la fonctionnalités (application.properties)
93. Spring Meetup - @esiber @interface21_ug 9393
Fichier de configuration normalisé
Spring Boot s’appuie sur un fichier de configuration normalisé
application.properties qui vise à paramétrer tous les éléments d’infrastructure
Support dans STS
94. Spring Meetup - @esiber @interface21_ug 9494
Fichier de configuration normalisé
Recommandation générale : ne pas mélanger les propriétés Spring Boot avec
vos propres propriétés, et plutôt dédier un fichier aux spécificités applicatives
Il est possible de définir ses propres clés de configuration dans ce
application.properties mais leur chargement nécessitera de mettre en place un
PropertySourcesPlaceholderConfigurer
Remarque : configuration avancée possible
➢ Il est possible d’étendre les mécanismes Spring Boot pour intégrer vos propres propriétés (et
se passer du PropertySourcesPlaceholderConfigurer)
➢ On peut aller jusqu’à les documenter et les proposer dans STS
95. Spring Meetup - @esiber @interface21_ug 9595
Classe de démarrage d’une application Spring Boot
Cette classe est annotée @SpringBootApplication
96. Spring Meetup - @esiber @interface21_ug 9696
Périmètre du chargement des beans @nnotés
@Configuration
➢ Aucun chargement de bean externe à la
classe de configuration n’est provoqué
➢ Nécessiter d’y joindre @ComponentScan
pour charger des beans annotés
➢ @ComponentScan définit un
base-package par défaut au package
courant
@SpringBootApplication
➢ Hérite des caractéristiques de
@Configuration et @ComponentScan
➢ A donc pour effet de définir un base-package
au package courant
➢ Attribut scanBasePackages équivalent au
basePackages de @ComponentScan
97. Spring Meetup - @esiber @interface21_ug 9797
Cohabitation avec des déclarations XML
Spring Boot n’est pas une solution excluant l’usage de déclarations XML
L’import d’un fichier XML est rendue possible par l’annotation
@ImportResource (Java Config) apposée (par exemple) sur la classe annotée
@SpringBootApplication
98. Spring Meetup - @esiber @interface21_ug 9898
Activation de la prise en charge d’aspects
Pour chaque syntaxe XML d’activation d’aspect on trouve une annotation
équivalente à apposer sur une classe de configuration pour activer la
fonctionnalité.
Ex. avec @EnableAsync
Sur une application Spring Boot, il peut arriver que certains aspects soient
déjà activés par défaut … c’est ce qu’on appelle l’auto-configuration (laquelle
est implicite sur une application Spring Boot)
Disclaimer : L’auto-configuration n’est pas chasse gardée des seules
applications Spring Boot
100. Spring Meetup - @esiber @interface21_ug 100100
Qu’est-ce qu’un contrôleur dans l’univers Spring ?
➢ C’est une classe de type POJO
➢ Déclarée à la fabrique par XML (rare), annotation @Controller (souvent)
ou Java Config
➢ Contenant des méthodes de signatures flexibles
○ Annotées @RequestMapping
○ Associées à une URL / verbe HTTP
○ Manipulant des représentations plus ou moins techniques de
concepts liés à HTTP (requête, réponse, session, etc.)
➢ Une infrastructure s’appuyant sur les standards Java EE que sont les APIs
JSP et Servlet
101. Spring Meetup - @esiber @interface21_ug 101101
Les différentes façons de démarrer une application
web Spring Boot
En ligne de commande :
➢ mvn spring-boot:run
➢ java -jar nomArtefact.jar
Pour le packaging jar, Spring démarre une application en intégrant par défaut
Tomcat comme conteneur de Servlets (1 processus = l’appli)
Alternative possible en changeant le type de packaging vers war et en
déployant dans un conteneur de Servlets (1 processus = le serveur pouvant
accueillir plusieurs applications)
102. Spring Meetup - @esiber @interface21_ug 102102
Choix du conteneur de Servlets intégré
Plusieurs conteneurs sont supportés par Spring Boot pour un fonctionnement
de type embedded
➢ Tomcat (default)
➢ Jetty
➢ Undertow
La sélection du conteneur se fait en agissant sur les starters / dépendances
Maven
103. Spring Meetup - @esiber @interface21_ug 103103
Déploiement au sein d’un conteneur de Servlets
Même si cela n’en est pas la philosophie recherchée, il est possible de
déployer votre application Spring Boot au sein d’un serveur applicatif
Remarque : n’empêche pas de continuer à tirer les bénéfices d’un démarrage
en ligne de commande (mode embedded) avec notamment les DevTools
Déploiement du nouvel artefact au sein d’un serveur (conteneur de Servlets) :
➢ en mode développement au sein d’un serveur configuré dans STS
➢ en autonome dans un serveur installé / configuré et démarré sur la machine cible
104. Spring Meetup - @esiber @interface21_ug 104104
Alterner entre Spring Boot embedded et Tomcat : facile ?
Disclaimer : ne déployez pas les yeux fermés au sein d’un conteneur de
Servlets après avoir développé/testé en embedded (ex. Classloader)
Pré-requis :
➢ Le packaging doit être à war au lieu de jar
@Override
protected SpringApplicationBuilder
configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
➢ Le starter dédié à Tomcat doit avoir un scope l’excluant du packaging
(impact sur le démarrage en ligne de commande avec Maven et java -jar
➢ Votre classe Spring Boot doit étendre SpringBootServletInitializer
105. Spring Meetup - @esiber @interface21_ug
Eléments à considérer sans “la magie” Spring Boot
Avec une application Spring Boot il est tentant d’assumer l’idée consistant à ce
que 1 application = 1 contexte Spring
C’est une vision simplifiée :
➢ Il est possible de créer autant de contextes Spring (silos) que souhaité dans la même
application (cf. ClassPathXmlApplicationContext)
➢ Spring permet même d’établir des liens entre différents contextes : hiérarchie de contextes
Cas particulier de l’architecture d’une application Web : 1 contexte parent + 1 à
plusieurs contextes enfants
Remarque : élément indispensable à considérer si on veut mêler contrôleurs
Web et API REST dans la même application
105
106. Spring Meetup - @esiber @interface21_ug 106
Architecture Spring MVC classique
Les classes DispatcherServlet et
ContextLoaderListener sont au coeur de
l’architecture MVC2 de Spring MVC
Elles peuvent être déclarées / configurées
● dans le fichier web.xml
● en Java depuis Spring 3.1 / Servlets 3.0
107. Spring Meetup - @esiber @interface21_ug 107107
Quelques conseils pour finir
Gardez en tête les patterns mis en oeuvre par Spring et le cycle de vie de la fabrique
Ne vous laissez pas aveugler par la magie de Spring Boot et Java Config : un peu de XML
est parfois plus explicite, compréhensible, et moins sujet à détournement des
mécanismes Spring … voire incontournable
Ne sautez pas les yeux fermés sur Spring Boot s’il s’agit de construire un monolithe sans
en comprendre les mécanismes et être capable de faire de votre projet un projet
modulaire
N’hésitez pas à tirer profit de fonctionnalités associées à Spring Boot mais qui ne
requièrent pas de créer une application Spring Boot pour être utilisées
108. Spring Meetup - @esiber @interface21_ug 108108
Contribuer ?
Initiative récente appelée “first-timers” visant à favoriser la diversité dans les
contributions en réservant le traitement de ticket à de nouveaux contributeurs
➢ first-timers issues on Spring Boot project
➢ ideal-for-contribution issues on Spring Boot project
109. Spring Meetup - @esiber @interface21_ug
Ressources
109
➢ Documentation de référence Spring Framework
➢ JavaDoc Spring Framework
➢ Documentation de référence Spring Security
➢ JavaDoc Spring Security
➢ Documentation de référence Spring Boot
➢ JavaDoc Spring Boot
➢ Spring Tools
➢ Les projets Spring sur Github
➢ Les guides de démarrage rapide
➢ Le compte twitter officiel
➢ Le compte SlideShare officiel
➢ La chaîne Youtube officielle