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.
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
| # | Chapitre | Contenu |
|---|---|---|
| 1 | JPA & Base de Données | Problème N+1, Lazy/Eager loading, @Transactional, pagination, relations entre entités |
| 2 | Exercices de Refactoring | Guard clauses, Strategy Pattern, SRP (God Class), constantes magiques, composition vs héritage |
| 3 | Algorithmes & Structures de Données | HashMap, Stack, LinkedList, Binary Search, Two Sum, FizzBuzz, anagrammes |
| 4 | Conception REST & Design Patterns | API REST, Builder, Singleton, Observer avec Spring Events |
| 5 | Débogage & Revue de Code | Trouver les bugs, revue de code, fuite mémoire, concurrence, exceptions, code smells |
| 6 | Pièges Java Fondamentaux | == vs .equals(), hashCode(), final, static, String immuable, Optional, passage par valeur |
| 7 | Collections Java | List.of() vs new ArrayList<>(), HashMap, HashSet, Stream API, thread-safety, itération |
| 8 | "C'est quoi...?" — 30 concepts | DTO, 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:
| Aspect | Spring Framework | Spring Boot |
|---|---|---|
| Configuration | Manuelle (XML ou Java) | Auto-configuration |
| Serveur | Serveur externe requis | Serveur intégré (Tomcat) |
| Dépendances | Gérées individuellement | Starters pré-configurés |
| Démarrage | Complexe | main() + @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:
@Controllerretourne des noms de vues (templates HTML). Pour retourner du JSON, il faut ajouter@ResponseBodysur 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:
| Scope | Description |
|---|---|
| singleton | Une seule instance par conteneur (par défaut) |
| prototype | Nouvelle instance à chaque injection |
| request | Une instance par requête HTTP |
| session | Une instance par session HTTP |
| application | Une 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(), retourneListau lieu deIterable
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:
- Si
spring-boot-starter-data-jpaest dans le classpath ET qu'uneDataSourceest configurée → auto-configure Hibernate, EntityManager, etc. - Si
spring-boot-starter-webest dans le classpath → auto-configure Tomcat, Jackson, DispatcherServlet - 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:
@ExceptionHandlerdans un contrôleur (portée locale)@RestControllerAdviceavec@ExceptionHandler(portée globale)@ResponseStatussur 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 FETCHen 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:
- Créer les objets (beans)
- Configurer les objets
- Assembler les dépendances
- 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:
| Propagation | Comportement |
|---|---|
REQUIRED (défaut) | Rejoint la transaction existante ou en crée une nouvelle |
REQUIRES_NEW | Crée toujours une nouvelle transaction (suspend l'existante) |
SUPPORTS | Rejoint si existante, sinon exécute sans transaction |
NOT_SUPPORTED | Exécute toujours sans transaction (suspend l'existante) |
MANDATORY | Transaction existante requise, sinon exception |
NEVER | Pas de transaction, sinon exception |
NESTED | Transaction 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:
-
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
-
Cache:
@Cacheableavec Spring Cache (Redis, Caffeine)- Cache HTTP (ETag, Cache-Control)
-
Configuration:
- Connection pooling (HikariCP configuré correctement)
- Compression GZIP
- Profils optimisés pour la production
-
Architecture:
- Opérations asynchrones (
@Async) - Indexation BDD appropriée
- Lazy loading des relations
- Opérations asynchrones (
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:
| Endpoint | Description |
|---|---|
/actuator/health | État de l'application (UP/DOWN) |
/actuator/info | Informations sur l'application |
/actuator/metrics | Métriques (mémoire, CPU, requêtes) |
/actuator/env | Variables d'environnement |
/actuator/beans | Liste de tous les beans |
/actuator/mappings | Tous les endpoints REST |
/actuator/loggers | Configuration des loggers |
/actuator/prometheus | Mé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:
- Actuator metrics : vérifier
/actuator/metrics/http.server.requestspour identifier les endpoints lents - Logs : activer
logging.level.org.hibernate.SQL=DEBUGpour voir les requêtes SQL - Problème N+1 : vérifier le nombre de requêtes avec
spring.jpa.show-sql=true - Connection pool : vérifier les métriques HikariCP (
hikaricp.connections.active) - Profiling : VisualVM ou JFR (Java Flight Recorder)
- Index BDD : analyser les requêtes lentes avec
EXPLAIN ANALYZE - 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