Aller au contenu principal

Module 18: Questions d'Entrevue Spring Boot

Objectifs​

Ce module vous prépare aux entrevues techniques en développement Java/Spring Boot. Les questions sont organisées par niveau de difficulté et par thème, couvrant les sujets les plus fréquemment posés en entrevue.

Conseil

Ne mémorisez pas les réponses mot pour mot. Comprenez les concepts et soyez capable de les expliquer dans vos propres mots avec des exemples concrets.


Chapitres du Module​

#ChapitreContenu
1JPA & Base de DonnéesProblème N+1, Lazy/Eager loading, @Transactional, pagination, relations entre entités
2Exercices de RefactoringGuard clauses, Strategy Pattern, SRP (God Class), constantes magiques, composition vs héritage
3Algorithmes & Structures de DonnéesHashMap, Stack, LinkedList, Binary Search, Two Sum, FizzBuzz, anagrammes
4Conception REST & Design PatternsAPI REST, Builder, Singleton, Observer avec Spring Events
5Débogage & Revue de CodeTrouver les bugs, revue de code, fuite mémoire, concurrence, exceptions, code smells
6Pièges Java Fondamentaux== vs .equals(), hashCode(), final, static, String immuable, Optional, passage par valeur
7Collections JavaList.of() vs new ArrayList<>(), HashMap, HashSet, Stream API, thread-safety, itération
8"C'est quoi...?" — 30 conceptsDTO, MVC, API REST, CRUD, POJO, Bean, IoC, ORM/JPA, Maven, Docker, JWT, CORS, Lombok, Record...

Niveau 1 : Questions Fondamentales​

Q1. Qu'est-ce que Spring Boot et en quoi diffère-t-il de Spring Framework?​

Réponse attendue:

Spring Boot est un framework construit au-dessus de Spring Framework qui simplifie la configuration et le déploiement. Les différences principales:

AspectSpring FrameworkSpring Boot
ConfigurationManuelle (XML ou Java)Auto-configuration
ServeurServeur externe requisServeur intégré (Tomcat)
DépendancesGérées individuellementStarters pré-configurés
DémarrageComplexemain() + @SpringBootApplication

Spring Boot ne remplace pas Spring, il le rend plus facile à utiliser.


Q2. Que fait l'annotation @SpringBootApplication?​

Réponse attendue:

C'est une méta-annotation qui combine trois annotations:

  • @SpringBootConfiguration : indique une classe de configuration Spring
  • @EnableAutoConfiguration : active l'auto-configuration basée sur les dépendances du classpath
  • @ComponentScan : scanne le package courant et ses sous-packages pour trouver les beans

Q3. Qu'est-ce que l'injection de dépendances (DI)?​

Réponse attendue:

L'injection de dépendances est un patron de conception où les dépendances d'un objet sont fournies de l'extérieur plutôt que créées par l'objet lui-même.

// SANS DI (couplage fort)
public class OrderService {
private UserRepository repo = new UserRepository(); // Crée sa propre dépendance
}

// AVEC DI (couplage faible)
public class OrderService {
private final UserRepository repo;

public OrderService(UserRepository repo) { // Injectée de l'extérieur
this.repo = repo;
}
}

Avantages: testabilité, découplage, flexibilité.


Q4. Quelle est la différence entre @Controller et @RestController?​

Réponse attendue:

  • @Controller retourne des noms de vues (templates HTML). Pour retourner du JSON, il faut ajouter @ResponseBody sur chaque méthode.
  • @RestController = @Controller + @ResponseBody. Chaque méthode retourne directement des données sérialisées en JSON.

Q5. Quels sont les différents scopes de bean dans Spring?​

Réponse attendue:

ScopeDescription
singletonUne seule instance par conteneur (par défaut)
prototypeNouvelle instance à chaque injection
requestUne instance par requête HTTP
sessionUne instance par session HTTP
applicationUne instance par ServletContext

Q6. Quelle est la différence entre application.properties et application.yml?​

Réponse attendue:

Même fonctionnalité, syntaxe différente:

# application.properties (clé=valeur, plat)
server.port=8080
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
# application.yml (hiérarchique, plus lisible)
server:
port: 8080
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb

YAML est plus lisible pour les configurations imbriquées, mais attention à l'indentation.


Q7. Qu'est-ce qu'un Starter Spring Boot?​

Réponse attendue:

Un starter est un ensemble de dépendances pré-configurées pour un usage spécifique:

  • spring-boot-starter-web : application web (Tomcat, Spring MVC, Jackson)
  • spring-boot-starter-data-jpa : persistance (Hibernate, Spring Data JPA)
  • spring-boot-starter-security : sécurité (Spring Security)
  • spring-boot-starter-test : tests (JUnit, Mockito, MockMvc)

Ils évitent de gérer manuellement les compatibilités entre versions.


Niveau 2 : Questions Intermédiaires​

Q8. Expliquez l'architecture en couches d'une application Spring Boot.​

Réponse attendue:

Client HTTP
↓
┌─────────────────┐
│ Controller │ Reçoit les requêtes, valide, retourne les réponses
├─────────────────┤
│ Service │ Logique métier, règles business, orchestration
├─────────────────┤
│ Repository │ Accès aux données (CRUD, requêtes BDD)
├─────────────────┤
│ Database │ PostgreSQL, MySQL, H2...
└─────────────────┘

Chaque couche ne communique qu'avec la couche directement en dessous. Le Controller n'accède jamais directement au Repository.


Q9. Quelle est la différence entre JpaRepository, CrudRepository et PagingAndSortingRepository?​

Réponse attendue:

JpaRepository (le plus complet)
↑ hérite de
PagingAndSortingRepository (pagination + tri)
↑ hérite de
CrudRepository (CRUD de base)
↑ hérite de
Repository (marqueur)
  • CrudRepository : save(), findById(), findAll(), deleteById()
  • PagingAndSortingRepository : ajoute findAll(Pageable), findAll(Sort)
  • JpaRepository : ajoute flush(), saveAndFlush(), deleteInBatch(), retourne List au lieu de Iterable

En pratique, on utilise presque toujours JpaRepository.


Q10. Comment fonctionne l'auto-configuration dans Spring Boot?​

Réponse attendue:

Spring Boot examine le classpath au démarrage et configure automatiquement les beans nécessaires:

  1. Si spring-boot-starter-data-jpa est dans le classpath ET qu'une DataSource est configurée → auto-configure Hibernate, EntityManager, etc.
  2. Si spring-boot-starter-web est dans le classpath → auto-configure Tomcat, Jackson, DispatcherServlet
  3. Les @ConditionalOn... annotations déterminent si une auto-configuration s'applique

On peut toujours surcharger les beans auto-configurés avec nos propres @Bean.


Q11. Qu'est-ce que Spring Profiles et à quoi ça sert?​

Réponse attendue:

Les profiles permettent de charger des configurations différentes selon l'environnement:

# application-dev.yml
spring:
datasource:
url: jdbc:h2:mem:devdb

# application-prod.yml
spring:
datasource:
url: jdbc:postgresql://prod-server:5432/mydb

Activation: --spring.profiles.active=prod ou SPRING_PROFILES_ACTIVE=prod

On peut aussi conditionner des beans avec @Profile("dev").


Q12. Expliquez la différence entre @Transactional en lecture et en écriture.​

Réponse attendue:

@Transactional(readOnly = true)   // Lecture : optimisation Hibernate (pas de dirty checking)
public List<User> findAll() { ... }

@Transactional // Écriture : commit si succès, rollback si exception
public User create(UserDto dto) { ... }

Bonne pratique: Mettre @Transactional(readOnly = true) au niveau de la classe service, et @Transactional sur les méthodes d'écriture uniquement.


Q13. Comment gère-t-on les exceptions dans une API REST Spring Boot?​

Réponse attendue:

Trois approches, de la plus locale à la plus globale:

  1. @ExceptionHandler dans un contrôleur (portée locale)
  2. @RestControllerAdvice avec @ExceptionHandler (portée globale)
  3. @ResponseStatus sur une exception custom

La meilleure pratique est le @RestControllerAdvice global qui centralise toute la gestion d'erreurs.


Q14. Qu'est-ce que le problème N+1 en JPA et comment le résoudre?​

Réponse attendue:

Le problème N+1 survient quand on charge une entité et que JPA exécute N requêtes supplémentaires pour charger les relations:

1 requête pour charger 100 départements
+ 100 requêtes pour charger les employés de chaque département
= 101 requêtes au lieu de 1 ou 2

Solutions:

  • JOIN FETCH en JPQL : @Query("SELECT d FROM Department d JOIN FETCH d.employees")
  • @EntityGraph : @EntityGraph(attributePaths = {"employees"})
  • @BatchSize : charge les relations par lots

Q15. Comment sécuriser une API REST avec JWT?​

Réponse attendue:

Le flux JWT:

1. Client envoie login/password → POST /api/auth/login
2. Serveur vérifie les credentials
3. Si OK → génère un JWT signé et le retourne
4. Client stocke le JWT
5. Pour chaque requête → Authorization: Bearer <token>
6. JwtAuthenticationFilter extrait et valide le token
7. Si valide → authentifie l'utilisateur dans le SecurityContext

Composants clés: JwtService (génération/validation), JwtAuthenticationFilter (filtre), SecurityConfig (configuration).


Niveau 3 : Questions Avancées​

Q16. Expliquez le pattern IoC (Inversion of Control) dans Spring.​

Réponse attendue:

IoC inverse le flux de contrôle : au lieu que le code crée ses dépendances, le conteneur Spring les crée et les injecte.

Le conteneur Spring (ApplicationContext) est responsable de:

  1. Créer les objets (beans)
  2. Configurer les objets
  3. Assembler les dépendances
  4. Gérer le cycle de vie

L'injection de dépendances (DI) est le mécanisme principal d'IoC dans Spring.


Q17. Quelle est la différence entre @Component, @Service, @Repository et @Controller?​

Réponse attendue:

Techniquement, les quatre sont des @Component. La différence est sémantique (rôle dans l'architecture):

  • @Component : bean générique
  • @Service : logique métier
  • @Repository : accès données + traduction automatique des exceptions SQL en exceptions Spring
  • @Controller : gestion des requêtes web

Utiliser la bonne annotation aide à la lisibilité et permet des traitements spécifiques (ex: traduction d'exceptions pour @Repository).


Q18. Comment implémenter la pagination dans Spring Data JPA?​

Réponse attendue:

// Repository
public interface UserRepository extends JpaRepository<User, Long> {
Page<User> findByRole(Role role, Pageable pageable);
}

// Controller
@GetMapping("/users")
public Page<User> getUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size,
@RequestParam(defaultValue = "name") String sortBy) {
Pageable pageable = PageRequest.of(page, size, Sort.by(sortBy));
return userRepository.findAll(pageable);
}

Le Page<T> retourné contient: contenu, numéro de page, taille, total d'éléments, nombre de pages.


Q19. Expliquez les différentes stratégies de propagation de @Transactional.​

Réponse attendue:

PropagationComportement
REQUIRED (défaut)Rejoint la transaction existante ou en crée une nouvelle
REQUIRES_NEWCrée toujours une nouvelle transaction (suspend l'existante)
SUPPORTSRejoint si existante, sinon exécute sans transaction
NOT_SUPPORTEDExécute toujours sans transaction (suspend l'existante)
MANDATORYTransaction existante requise, sinon exception
NEVERPas de transaction, sinon exception
NESTEDTransaction imbriquée (savepoint)

Cas d'usage fréquent de REQUIRES_NEW : log d'audit qui doit persister même si la transaction principale échoue.


Q20. Comment optimiser les performances d'une application Spring Boot?​

Réponse attendue:

  1. JPA/Hibernate:

    • Éviter le problème N+1 (JOIN FETCH, EntityGraph)
    • Utiliser @Transactional(readOnly = true) pour les lectures
    • Projections DTO au lieu d'entités complètes
    • Pagination systématique
  2. Cache:

    • @Cacheable avec Spring Cache (Redis, Caffeine)
    • Cache HTTP (ETag, Cache-Control)
  3. Configuration:

    • Connection pooling (HikariCP configuré correctement)
    • Compression GZIP
    • Profils optimisés pour la production
  4. Architecture:

    • Opérations asynchrones (@Async)
    • Indexation BDD appropriée
    • Lazy loading des relations

Q21. Qu'est-ce que Spring Actuator et quels endpoints utiles fournit-il?​

Réponse attendue:

Spring Actuator fournit des endpoints de monitoring et de gestion:

EndpointDescription
/actuator/healthÉtat de l'application (UP/DOWN)
/actuator/infoInformations sur l'application
/actuator/metricsMétriques (mémoire, CPU, requêtes)
/actuator/envVariables d'environnement
/actuator/beansListe de tous les beans
/actuator/mappingsTous les endpoints REST
/actuator/loggersConfiguration des loggers
/actuator/prometheusMétriques au format Prometheus

En production, il faut sécuriser ces endpoints et n'exposer que /health et /info publiquement.


Q22. Expliquez le cycle de vie d'un bean Spring.​

Réponse attendue:

1. Instanciation (constructeur)
2. Injection des dépendances (@Autowired)
3. Aware interfaces (BeanNameAware, ApplicationContextAware...)
4. BeanPostProcessor.postProcessBeforeInitialization()
5. @PostConstruct
6. InitializingBean.afterPropertiesSet()
7. init-method personnalisé
8. BeanPostProcessor.postProcessAfterInitialization()
9. ══════ Bean prêt à l'utilisation ══════
10. @PreDestroy
11. DisposableBean.destroy()
12. destroy-method personnalisé

En pratique, on utilise surtout @PostConstruct et @PreDestroy.


Q23. Comment implémenter un pattern CQRS simplifié avec Spring Boot?​

Réponse attendue:

CQRS (Command Query Responsibility Segregation) sépare les opérations de lecture et d'écriture:

// Command (écriture)
@Service
@Transactional
public class UserCommandService {
public User create(CreateUserCommand cmd) { ... }
public void update(UpdateUserCommand cmd) { ... }
public void delete(Long id) { ... }
}

// Query (lecture)
@Service
@Transactional(readOnly = true)
public class UserQueryService {
public UserDto findById(Long id) { ... }
public Page<UserDto> findAll(Pageable page) { ... }
}

Cela permet d'optimiser les lectures et écritures séparément (ex: projections DTO pour les lectures, validations complexes pour les écritures).


Questions Comportementales / Scénarios​

Q24. Vous devez concevoir une API REST pour un système de e-commerce. Quels endpoints créez-vous?​

Réponse attendue:

Products:
GET /api/products → Liste paginée
GET /api/products/{id} → Détail d'un produit
POST /api/products → Créer (ADMIN)
PUT /api/products/{id} → Modifier (ADMIN)
DELETE /api/products/{id} → Supprimer (ADMIN)

Orders:
POST /api/orders → Passer une commande
GET /api/orders → Mes commandes
GET /api/orders/{id} → Détail d'une commande
PATCH /api/orders/{id} → Modifier statut (ADMIN)

Auth:
POST /api/auth/register → Inscription
POST /api/auth/login → Connexion (retourne JWT)
POST /api/auth/refresh → Rafraîchir le token

Cart:
GET /api/cart → Mon panier
POST /api/cart/items → Ajouter au panier
DELETE /api/cart/items/{id} → Retirer du panier

Q25. Votre application Spring Boot est lente en production. Comment diagnostiquez-vous?​

Réponse attendue:

  1. Actuator metrics : vérifier /actuator/metrics/http.server.requests pour identifier les endpoints lents
  2. Logs : activer logging.level.org.hibernate.SQL=DEBUG pour voir les requêtes SQL
  3. Problème N+1 : vérifier le nombre de requêtes avec spring.jpa.show-sql=true
  4. Connection pool : vérifier les métriques HikariCP (hikaricp.connections.active)
  5. Profiling : VisualVM ou JFR (Java Flight Recorder)
  6. Index BDD : analyser les requêtes lentes avec EXPLAIN ANALYZE
  7. Mémoire : vérifier le garbage collector et le heap size

Checklist de Préparation​

Avant votre entrevue, assurez-vous de pouvoir:

  • Expliquer l'IoC et la DI avec un exemple concret
  • Décrire l'architecture en couches d'une app Spring Boot
  • Écrire un CRUD complet (Controller → Service → Repository)
  • Expliquer JWT et le flux d'authentification
  • Parler de vos projets Spring Boot personnels
  • Décrire comment vous gérez les exceptions
  • Expliquer la différence entre les annotations clés
  • Parler de Docker et CI/CD avec Spring Boot
  • Connaître les bases de la pagination et du tri
  • Savoir diagnostiquer des problèmes de performance

⬅️ Retour à l'accueil